$(INSTALL) -d "$(DESTDIR)$(prefix)"
$(INSTALL) -d "$(DESTDIR)$(prefix)/$(libdir)"
$(INSTALL) -d "$(DESTDIR)$(prefix)/bin"
+ifeq ($(DISABLE_ISOFF), no)
$(INSTALL) $(INSTFLAGS) -m 755 bin/gcc/MP4Box "$(DESTDIR)$(prefix)/bin"
+endif
$(INSTALL) $(INSTFLAGS) -m 755 bin/gcc/MP4Client "$(DESTDIR)$(prefix)/bin"
if [ -d $(DESTDIR)$(prefix)/$(libdir)/pkgconfig ] ; then \
$(INSTALL) $(INSTFLAGS) -m 644 gpac.pc "$(DESTDIR)$(prefix)/$(libdir)/pkgconfig" ; \
$(INSTALL) -m 755 bin/gcc/libgpac.$(DYN_LIB_SUFFIX) $(DESTDIR)$(prefix)/$(libdir)/libgpac.$(VERSION).$(DYN_LIB_SUFFIX)
ln -sf libgpac.$(VERSION).$(DYN_LIB_SUFFIX) $(DESTDIR)$(prefix)/$(libdir)/libgpac.$(DYN_LIB_SUFFIX)
else
- $(INSTALL) $(INSTFLAGS) -m 755 bin/gcc/libgpac.$(DYN_LIB_SUFFIX) $(DESTDIR)$(prefix)/$(libdir)/libgpac.$(DYN_LIB_SUFFIX).$(VERSION)
- ln -sf libgpac.$(DYN_LIB_SUFFIX).$(VERSION) $(DESTDIR)$(prefix)/$(libdir)/libgpac.$(DYN_LIB_SUFFIX)
+ $(INSTALL) $(INSTFLAGS) -m 755 bin/gcc/libgpac.$(DYN_LIB_SUFFIX).$(VERSION_SONAME) $(DESTDIR)$(prefix)/$(libdir)/libgpac.$(DYN_LIB_SUFFIX).$(VERSION_SONAME)
+ ln -sf libgpac.$(DYN_LIB_SUFFIX).$(VERSION_SONAME) $(DESTDIR)$(prefix)/$(libdir)/libgpac.so.$(VERSION_MAJOR)
+ ln -sf libgpac.$(DYN_LIB_SUFFIX).$(VERSION_SONAME) $(DESTDIR)$(prefix)/$(libdir)/libgpac.so
ifeq ($(DESTDIR)$(prefix),$(prefix))
ldconfig || true
endif
ifeq ($(DISABLE_ISOFF), no)
APPDIRS+=mp4box
+ifeq ($(DISABLE_M2TS), no)
APPDIRS+=mp42ts
endif
+endif
V4STUDIODIR=
INSTDIRS=mp4client
#include <gpac/scene_manager.h>
-#ifdef GPAC_DISABLE_ISOM
+#if defined(GPAC_DISABLE_ISOM) || defined(GPAC_DISABLE_ISOM_WRITE)
#error "Cannot compile MP4Box if GPAC is not built with ISO File Format support"
void scene_coding_log(void *cbk, u32 log_level, u32 log_tool, const char *fmt, va_list vlist);
-#ifndef GPAC_DISABLE_ISOM_WRITE
+#if !defined(GPAC_DISABLE_ISOM_WRITE) && !defined(GPAC_DISABLE_MEDIA_IMPORT)
GF_Err import_file(GF_ISOFile *dest, char *inName, u32 import_flags, Double force_fps, u32 frames_per_sample);
#endif
/*SAF*/
else if (ftype==6) {
load.isom = gf_isom_open("saf_conv", GF_ISOM_WRITE_EDIT, NULL);
- if (load.isom) e = import_file(load.isom, file, 0, 0, 0);
- else e = gf_isom_last_error(NULL);
+#ifndef GPAC_DISABLE_MEDIA_IMPORT
+ if (load.isom)
+ e = import_file(load.isom, file, 0, 0, 0);
+ else
+#else
+ fprintf(stderr, "Warning: GPAC was compiled without Media Import support\n");
+#endif
+ e = gf_isom_last_error(NULL);
if (e) {
fprintf(stdout, "Error importing file: %s\n", gf_error_to_string(e));
fprintf(stdout, "SVG node printing is not supported\n");
return;
} else if (graph_type==1) {
+#ifndef GPAC_DISABLE_X3D
tag = gf_node_x3d_type_by_class_name(name);
std_name = "X3D";
+#else
+ fprintf(stdout, "X3D node printing is not supported (X3D support disabled)\n");
+ return;
+#endif
} else {
tag = gf_node_mpeg4_type_by_class_name(name);
std_name = "MPEG4";
u32 i, nb_in, nb_not_in, start_tag, end_tag;
if (graph_type==1) {
-#ifdef GPAC_DISABLE_VRML
+#if !defined(GPAC_DISABLE_VRML) && !defined(GPAC_DISABLE_X3D)
+ start_tag = GF_NODE_RANGE_FIRST_X3D;
+ end_tag = TAG_LastImplementedX3D;
+#else
fprintf(stdout, "X3D scene graph disabled in this build of GPAC\n");
return;
-#else
- start_tag = GF_NODE_RANGE_FIRST_X3D;
- end_tag = TAG_LastImplementedX3D;
#endif
} else if (graph_type==2) {
#ifdef GPAC_DISABLE_SVG
}
}
-#endif /*GPAC_DISABLE_ISOM*/
+#endif /*defined(GPAC_DISABLE_ISOM) || defined(GPAC_DISABLE_ISOM_WRITE)*/
#ifndef GPAC_DISABLE_MPEG2TS
char duration_string[100];
char buffer_string[100];
u32 bandwidth, i;
+#ifndef GPAC_DISABLE_MEDIA_IMPORT
GF_MediaImporter import;
+#endif
char szCodecs[1000];
u32 width, height, sample_rate, nb_channels, langCode;
GF_Err e;
FILE *mpd = index_info->mpd_file;
/*get codecs*/
+#ifndef GPAC_DISABLE_MEDIA_IMPORT
memset(&import, 0, sizeof(GF_MediaImporter));
import.trackID = 0;
import.flags = GF_IMPORT_PROBE_ONLY;
import.in_name = (char *)media_file_name;
e = gf_media_import(&import);
+#else
+ fprintf(stdout, "Warning: generating MPD without media import support\n");
+#endif
strcpy(szCodecs, "");
width = height = sample_rate = nb_channels = langCode = 0;
+
+ bandwidth = (u32) (file_size * 8 / file_duration);
+ mpd_duration(file_duration, duration_string);
+ mpd_duration(bufferTime, buffer_string);
+
+ if (!index_info->represantation_idx) {
+ fprintf(mpd, "<MPD type=\"%s\" xmlns=\"urn:mpeg:DASH:schema:MPD:2011\" profiles=\"urn:mpeg:dash:profile:mp2t-main:2011\" minBufferTime=\"%s\">\n", (on_demand ? "static": "dynamic"), buffer_string);
+ fprintf(mpd, " <ProgramInformation moreInformationURL=\"http://gpac.sourceforge.net\">\n");
+ fprintf(mpd, " <Title>MPD for file %s generated with GPAC %s</Title>\n", media_file_name, GPAC_FULL_VERSION);
+ fprintf(mpd, " </ProgramInformation>\n");
+ fprintf(mpd, " <Period start=\"PT0S\" duration=\"%s\" minBufferTime=\"%s\">\n", duration_string, buffer_string);
+ fprintf(mpd, " <AdaptationSet segmentAlignment=\"true\" bitstreamSwitching=\"true\" subsegmentAlignment=\"true\">\n");
+ }
+
if (!e) {
+#ifndef GPAC_DISABLE_MEDIA_IMPORT
for (i=0; i<import.nb_tracks;i++) {
if (strlen(import.tk_info[i].szCodecProfile)) {
if (strlen(szCodecs)) strcat(szCodecs, ",");
strcat(szCodecs, import.tk_info[i].szCodecProfile);
}
+
if (import.tk_info[i].type==GF_ISOM_MEDIA_VISUAL) {
if (!width) width = import.tk_info[i].video_info.width;
if (!height) height = import.tk_info[i].video_info.height;
+ fprintf(mpd, " <ContentComponent id=\"%d\" contentType=\"video\"/>\n", import.tk_info[i].track_num);
}
else if (import.tk_info[i].type==GF_ISOM_MEDIA_AUDIO) {
if (!sample_rate) sample_rate = import.tk_info[i].audio_info.sample_rate;
if (!nb_channels) nb_channels = import.tk_info[i].audio_info.nb_channels;
+ fprintf(mpd, " <ContentComponent id=\"%d\" contentType=\"audio\"/>\n", import.tk_info[i].track_num);
}
if (!langCode && import.tk_info[i].lang) langCode = import.tk_info[i].lang;
}
- }
-
- bandwidth = (u32) (file_size * 8 / file_duration);
- mpd_duration(file_duration, duration_string);
- mpd_duration(bufferTime, buffer_string);
-
- if (!index_info->represantation_idx) {
- fprintf(mpd, "<MPD type=\"%s\" xmlns=\"urn:mpeg:DASH:schema:MPD:2011\" profiles=\"urn:mpeg:dash:profile:mp2t-main:2011\" minBufferTime=\"%s\">\n", (on_demand ? "static": "dynamic"), buffer_string);
- fprintf(mpd, " <ProgramInformation moreInformationURL=\"http://gpac.sourceforge.net\">\n");
- fprintf(mpd, " <Title>MPD for file %s generated with GPAC %s</Title>\n", media_file_name, GPAC_FULL_VERSION);
- fprintf(mpd, " </ProgramInformation>\n");
- fprintf(mpd, " <Period start=\"PT0S\" duration=\"%s\" minBufferTime=\"%s\">\n", duration_string, buffer_string);
- fprintf(mpd, " <AdaptationSet segmentAlignment=\"true\" bitstreamSwitching=\"true\" subsegmentAlignment=\"true\">\n");
+#endif
}
fprintf(mpd, " <Representation id=\"%d\" mimeType=\"video/mp2t\" codecs=\"%s\"", index_info->represantation_idx+1, szCodecs);
/* add startIndex for live scenarios */
if (index_info->init_seg_name) {
- fprintf(index_info->mpd_file, " <InitialisationSegment sourceURL=\"%s\"/>\n", index_info->init_seg_name);
+ fprintf(index_info->mpd_file, " <Initialization sourceURL=\"%s\"/>\n", index_info->init_seg_name);
}
dumper.index_info.index_file = NULL;
dumper.index_info.index_bs = NULL;
if (dumper.index_info.use_url_template!=2) {
+#ifndef GPAC_DISABLE_ISOM_FRAGMENTS
dumper.index_info.index_file = gf_f64_open(dumper.index_info.index_file_name, "wb");
dumper.index_info.index_bs = gf_bs_from_file(dumper.index_info.index_file, GF_BITSTREAM_WRITE);
{
gf_isom_box_write((GF_Box *)styp, dumper.index_info.index_bs);
gf_isom_box_del((GF_Box *)styp);
}
+#endif
}
}
/*PES dumping*/
#ifndef GPAC_DISABLE_ISOM_WRITE
+#include <gpac/xml.h>
+
+typedef struct
+{
+ const char *root_file;
+ const char *dir;
+ GF_List *imports;
+} WGTEnum;
+
+#ifndef GPAC_DISABLE_MEDIA_IMPORT
+
extern u32 swf_flags;
extern Float swf_flatten_angle;
extern Bool keep_sys_tracks;
u32 di;
samp = gf_isom_get_sample(orig, i+1, j+1, &di);
last_DTS = samp->DTS;
- samp->DTS = (u64) (ts_scale * (s64)samp->DTS) + insert_dts;
+ samp->DTS = (u64) (ts_scale * samp->DTS + insert_dts);
samp->CTS_Offset = (u32) (samp->CTS_Offset * ts_scale);
if (gf_isom_is_self_contained(orig, i+1, di)) {
gf_isom_sample_del(&s);
}
gf_isom_sample_del(&samp);
- if (e) goto err_exit;
+ if (e)
+ goto err_exit;
gf_set_progress("Appending", nb_done, nb_samp);
nb_done++;
}
GF_SceneLoader load;
GF_SceneManager *ctx;
GF_SceneGraph *sg;
+#ifndef GPAC_DISABLE_SCENE_STATS
GF_StatManager *statsman = NULL;
+#endif
sg = gf_sg_new();
ctx = gf_sm_new(sg);
e = gf_sm_load_run(&load);
gf_sm_load_done(&load);
+#ifndef GPAC_DISABLE_SCENE_STATS
if (opts->auto_quant) {
fprintf(stdout, "Analysing Scene for Automatic Quantization\n");
statsman = gf_sm_stats_new();
#endif
}
}
+#endif /*GPAC_DISABLE_SCENE_STATS*/
if (e<0) {
fprintf(stdout, "Error loading file %s\n", gf_error_to_string(e));
gf_isom_modify_alternate_brand(mp4, GF_ISOM_BRAND_ISOM, 1);
err_exit:
+#ifndef GPAC_DISABLE_SCENE_STATS
if (statsman) gf_sm_stats_del(statsman);
+#endif
gf_sm_del(ctx);
gf_sg_del(sg);
return e;
*/
GF_Err EncodeFileChunk(char *chunkFile, char *bifs, char *inputContext, char *outputContext, const char *tmpdir)
{
-#ifdef GPAC_DISABLE_BIFS
- fprintf(stdout, "BIFS is not supported in this build of GPAC\n");
+#if defined(GPAC_DISABLE_BIFS_ENC) || defined(GPAC_DISABLE_SCENE_ENCODER) || defined (GPAC_DISABLE_SCENE_DUMP)
+ fprintf(stdout, "BIFS encoding is not supported in this build of GPAC\n");
return GF_NOT_SUPPORTED;
#else
GF_Err e;
gf_sm_del(ctx);
gf_sg_del(sg);
}
+
return e;
-#endif
+
+#endif /*defined(GPAC_DISABLE_BIFS_ENC) || defined(GPAC_DISABLE_SCENE_ENCODER) || defined (GPAC_DISABLE_SCENE_DUMP)*/
+
}
-#include <gpac/xml.h>
+#endif /*GPAC_DISABLE_MEDIA_IMPORT*/
+
void sax_node_start(void *sax_cbck, const char *node_name, const char *name_space, const GF_XMLAttribute *attributes, u32 nb_attributes)
{
}
}
-typedef struct
-{
- const char *root_file;
- const char *dir;
- GF_List *imports;
-} WGTEnum;
-
static Bool wgt_enum_files(void *cbck, char *file_name, char *file_path)
{
WGTEnum *wgt = (WGTEnum *)cbck;
#include <gpac/scene_engine.h>
#include <gpac/rtp_streamer.h>
+#if defined(GPAC_DISABLE_ISOM) || defined(GPAC_DISABLE_ISOM_WRITE)
+
+#error "Cannot compile MP4Box if GPAC is not built with ISO File Format support"
+
+#else
+
+#ifndef GPAC_DISABLE_STREAMING
+
void PrintStreamerUsage()
{
fprintf(stdout, "File Streamer Options\n"
}
+#endif /*GPAC_DISABLE_STREAMING*/
+
+#endif /*defined(GPAC_DISABLE_ISOM) || defined(GPAC_DISABLE_ISOM_WRITE)*/
/*in fileimport.c*/
#ifndef GPAC_DISABLE_ISOM_WRITE
-void convert_file_info(char *inName, u32 trackID);
+
GF_Err import_file(GF_ISOFile *dest, char *inName, u32 import_flags, Double force_fps, u32 frames_per_sample);
GF_Err split_isomedia_file(GF_ISOFile *mp4, Double split_dur, u32 split_size_kb, char *inName, Double InterleavingTime, Double chunk_start, Bool adjust_split_end, const char *tmpdir);
GF_Err cat_isomedia_file(GF_ISOFile *mp4, char *fileName, u32 import_flags, Double force_fps, u32 frames_per_sample, char *tmp_dir, Bool force_cat);
-#ifndef GPAC_DISABLE_SCENE_ENCODER
+#if !defined(GPAC_DISABLE_MEDIA_IMPORT) && !defined(GPAC_DISABLE_SCENE_ENCODER)
+void convert_file_info(char *inName, u32 trackID);
GF_Err EncodeFile(char *in, GF_ISOFile *mp4, GF_SMEncodeOptions *opts, FILE *logs);
GF_Err EncodeFileChunk(char *chunkFile, char *bifs, char *inputContext, char *outputContext, const char *tmpdir);
#endif
-
GF_ISOFile *package_file(char *file_name, char *fcc, const char *tmpdir, Bool make_wgt);
+
#endif
GF_Err dump_cover_art(GF_ISOFile *file, char *inName);
#ifndef GPAC_DISABLE_STREAMING
void PrintStreamerUsage();
int stream_file_rtp(int argc, char **argv);
-#endif
-
int live_session(int argc, char **argv);
void PrintLiveUsage();
+#endif
+
int mp4boxTerminal(int argc, char **argv);
u32 quiet = 0;
#ifndef GPAC_DISABLE_SCENE_ENCODER
GF_SMEncodeOptions opts;
#endif
- Double InterleavingTime, split_duration, split_start, import_fps, dash_duration;
+#ifndef GPAC_DISABLE_STREAMING
SDPLine sdp_lines[MAX_CUMUL_OPS];
+#endif
+ Double InterleavingTime, split_duration, split_start, import_fps, dash_duration;
MetaAction metas[MAX_CUMUL_OPS];
TrackAction tracks[MAX_CUMUL_OPS];
TSELAction tsel_acts[MAX_CUMUL_OPS];
nb_track_act++;
i++;
}
-#ifndef GPAC_DISABLE_MEDIA_EXPORT
+#if !defined(GPAC_DISABLE_MEDIA_EXPORT) && !defined(GPAC_DISABLE_MEDIA_IMPORT)
else if (!stricmp(arg, "-dref")) import_flags |= GF_IMPORT_USE_DATAREF;
else if (!stricmp(arg, "-no-drop") || !stricmp(arg, "-nodrop")) import_flags |= GF_IMPORT_NO_FRAME_DROP;
else if (!stricmp(arg, "-packed")) import_flags |= GF_IMPORT_FORCE_PACKED;
}
else if (!stricmp(arg, "-agg")) { CHECK_NEXT_ARG agg_samples = atoi(argv[i+1]); i++; }
else if (!stricmp(arg, "-keep-all") || !stricmp(arg, "-keepall")) import_flags |= GF_IMPORT_KEEP_ALL_TRACKS;
-#endif /*GPAC_DISABLE_MEDIA_EXPORT*/
+#endif /*!defined(GPAC_DISABLE_MEDIA_EXPORT) && !defined(GPAC_DISABLE_MEDIA_IMPORT*/
else if (!stricmp(arg, "-keep-sys") || !stricmp(arg, "-keepsys")) keep_sys_tracks = 1;
else if (!stricmp(arg, "-ms")) { CHECK_NEXT_ARG mediaSource = argv[i+1]; i++; }
else if (!stricmp(arg, "-mp4")) { encode = 1; open_edit = 1; }
opts.resolution = atoi(argv[i+1]);
i++;
}
+#ifndef GPAC_DISABLE_SCENE_STATS
else if (!stricmp(arg, "-auto-quant")) {
CHECK_NEXT_ARG
opts.resolution = atoi(argv[i+1]);
opts.auto_quant = 1;
i++;
}
+#endif
else if (!stricmp(arg, "-coord-bits")) {
CHECK_NEXT_ARG
opts.coord_bits = atoi(argv[i+1]);
else if (!strcmp(argv[i+1], "crypt")) PrintEncryptUsage();
else if (!strcmp(argv[i+1], "meta")) PrintMetaUsage();
else if (!strcmp(argv[i+1], "swf")) PrintSWFUsage();
+#ifndef GPAC_DISABLE_STREAMING
else if (!strcmp(argv[i+1], "rtp")) PrintStreamerUsage();
else if (!strcmp(argv[i+1], "live")) PrintLiveUsage ();
+#endif
else if (!strcmp(argv[i+1], "all")) {
PrintGeneralUsage();
PrintExtractUsage();
PrintEncryptUsage();
PrintMetaUsage();
PrintSWFUsage();
+#ifndef GPAC_DISABLE_STREAMING
PrintStreamerUsage();
PrintLiveUsage ();
+#endif
}
else PrintUsage();
return 0;
return 1;
}
+#ifndef GPAC_DISABLE_STREAMING
if (live_scene) {
return live_session(argc, argv);
}
-#ifndef GPAC_DISABLE_STREAMING
if (stream_rtp) {
return stream_file_rtp(argc, argv);
}
}
#endif
-#if !defined(GPAC_DISABLE_ISOM_WRITE) && !defined(GPAC_DISABLE_SCENE_ENCODER)
+#if !defined(GPAC_DISABLE_ISOM_WRITE) && !defined(GPAC_DISABLE_SCENE_ENCODER) && !defined(GPAC_DISABLE_MEDIA_IMPORT)
else if (chunk_mode) {
if (!inName) {
fprintf(stdout, "chunk encoding syntax: [-outctx outDump] -inctx inScene auFile\n");
}
#endif
else if (encode) {
-#if !defined(GPAC_DISABLE_ISOM_WRITE) && !defined(GPAC_DISABLE_SCENE_ENCODER)
+#if !defined(GPAC_DISABLE_ISOM_WRITE) && !defined(GPAC_DISABLE_SCENE_ENCODER) && !defined(GPAC_DISABLE_MEDIA_IMPORT)
FILE *logs = NULL;
if (do_log) {
char logfile[5000];
#ifndef GPAC_DISABLE_ISOM_WRITE
else if (!open_edit && file_exists /* && !gf_isom_probe_file(inName) */ && !dump_mode) {
/*************************************************************************************************/
+#ifndef GPAC_DISABLE_MEDIA_IMPORT
if(dvbhdemux)
{
GF_MediaImporter import;
return 1;
}
}
+#endif /*GPAC_DISABLE_MEDIA_IMPORT*/
if (dash_duration) {
if (subsegs_per_sidx<0) subsegs_per_sidx = 0;
#ifndef GPAC_DISABLE_MPEG2TS
dump_mpeg2_ts(inName, pes_dump, program_number, 0, 0, 0, NULL, NULL, 0, 0, 0, 0);
#endif
+#ifndef GPAC_DISABLE_MEDIA_IMPORT
} else {
convert_file_info(inName, info_track_id);
+#endif
}
return 0;
}
-
-
-#endif
+#endif /*GPAC_DISABLE_ISOM_WRITE*/
else if (open_edit) {
file = gf_isom_open(inName, GF_ISOM_WRITE_EDIT, tmpdir);
if (!outName && file) outName = inName;
}
}
-#ifndef GPAC_DISABLE_ISOM_WRITE
+#if !(definedGPAC_DISABLE_ISOM_WRITE) && !defined(GPAC_DISABLE_MEDIA_IMPORT)
if (split_duration || split_size) {
split_isomedia_file(file, split_duration, split_size, inName, InterleavingTime, split_start, adjust_split_end, tmpdir);
/*never save file when splitting is desired*/
strcat(outfile, ".m21");
}
}
+#ifndef GPAC_DISABLE_MEDIA_IMPORT
if ((conv_type == GF_ISOM_CONV_TYPE_ISMA) || (conv_type == GF_ISOM_CONV_TYPE_ISMA_EX)) {
fprintf(stdout, "Converting to ISMA Audio-Video MP4 file...\n");
/*keep ESIDs when doing ISMACryp*/
if (e) goto err_exit;
needSave = 1;
}
+#endif /*GPAC_DISABLE_MEDIA_IMPORT*/
if (conv_type == GF_ISOM_CONV_TYPE_IPOD) {
u32 major_brand = 0;
}
if (!seg_name) use_url_template = 0;
- gf_media_mpd_start(szMPD, (char *)gf_isom_get_filename(file), use_url_template, single_segment, dash_ctx, szInit, period_duration);
+ gf_media_mpd_start(szMPD, (char *)gf_isom_get_filename(file), use_url_template, single_segment, dash_ctx, init_seg, period_duration);
for (i=0; i<nb_dash_inputs; i++) {
char szSegName[GF_MAX_PATH], *segment_name;
if (nb_dash_inputs>1) {
fprintf(stdout, "DASHing file %s\n", dash_inputs[i]);
}
+#ifndef GPAC_DISABLE_ISOM_FRAGMENTS
e = gf_media_fragment_file(in, outfile, szMPD, InterleavingTime, seg_at_rap ? 2 : 1, dash_duration, segment_name, seg_ext, subsegs_per_sidx, daisy_chain_sidx, use_url_template, single_segment, dash_ctx, init_seg, i+1);
+#else
+ fprintf(stderr, "GPAC was compiled without fragment support\n");
+ e = GF_NOT_SUPPORTED;
+#endif
if (e) {
fprintf(stdout, "Error while DASH-ing file: %s\n", gf_error_to_string(e));
break;
gf_isom_delete(file);
gf_sys_close();
return (e!=GF_OK) ? 1 : 0;
+#ifndef GPAC_DISABLE_ISOM_FRAGMENTS
} else if (Frag) {
if (!InterleavingTime) InterleavingTime = 0.5;
if (HintIt) fprintf(stdout, "Warning: cannot hint and fragment - ignoring hint\n");
}
gf_sys_close();
return (e!=GF_OK) ? 1 : 0;
+#endif
}
#ifndef GPAC_DISABLE_ISOM_HINTING
if (e) goto err_exit;
}
if (chap_file) {
+#ifndef GPAC_DISABLE_MEDIA_IMPORT
e = gf_media_import_chapters(file, chap_file, import_fps);
needSave = 1;
+#else
+ fprintf(stdout, "Warning: GPAC compiled without Media Import, chapters can't be imported\n");
+ e = GF_NOT_SUPPORTED;
+#endif
if (e) goto err_exit;
}
"\n"
"\tp: play/pause the presentation\n"
"\ts: step one frame ahead\n"
- "\tz: seek into presentation\n"
+ "\tz: seek into presentation by percentage\n"
+ "\tT: seek into presentation by time\n"
"\tt: print current timing\n"
"\n"
"\tu: sends a command (BIFS or LASeR) to the main scene\n"
break;
case 'z':
+ case 'T':
if (!CanSeek || (Duration<=2000)) {
fprintf(stdout, "scene not seekable\n");
} else {
fprintf(stdout, "Duration: ");
PrintTime(Duration);
res = gf_term_get_time_in_ms(term);
- res *= 100; res /= (s64)Duration;
- fprintf(stdout, " (current %.2f %%)\nEnter Seek percentage:\n", res);
- if (scanf("%d", &seekTo) == 1) {
- if (seekTo > 100) seekTo = 100;
- res = (Double)(s64)Duration; res /= 100; res *= seekTo;
- gf_term_play_from_time(term, (u64) (s64) res, 0);
+ if (c=='z') {
+ res *= 100; res /= (s64)Duration;
+ fprintf(stdout, " (current %.2f %%)\nEnter Seek percentage:\n", res);
+ if (scanf("%d", &seekTo) == 1) {
+ if (seekTo > 100) seekTo = 100;
+ res = (Double)(s64)Duration; res /= 100; res *= seekTo;
+ gf_term_play_from_time(term, (u64) (s64) res, 0);
+ }
+ } else {
+ u32 r, h, m, s;
+ fprintf(stdout, " - Current Time: ");
+ PrintTime((u64) res);
+ fprintf(stdout, "\nEnter seek time (Format: s, m:s or h:m:s):\n");
+ h = m = s = 0;
+ r =scanf("%d:%d:%d", &h, &m, &s);
+ if (r==2) { s = m; m = h; h = 0; }
+ else if (r==1) { s = h; m = h = 0; }
+
+ if (r && (r<=3)) {
+ u64 time = h*3600 + m*60 + s;
+ gf_term_play_from_time(term, time*1000, 0);
+ }
}
}
break;
+++ /dev/null
-CabWiz gpac.inf
-ezsetup -l english -i gpac.ini -r readme.txt -e ../../../COPYING -o GPAC_0.4.2_Setup_arm_ppc02.exe
-del *.cab
-del *.dat
+++ /dev/null
-[Version]
-Signature = "$Windows NT$"
-Provider = "GPAC 0.4.2"
-CESignature = "$Windows CE$"
-
-[CEStrings]
-;Osmo4 for PocketPC install, Osmophone for Smartphone install
-AppName = Osmo4
-InstallDir = \Program Files\GPAC
-
-[Strings]
-;Osmo4.exe for PocketPC install, Osmophone.exe for Smartphone install
-ExeName = Osmo4.exe
-
-[DefaultInstall]
-CopyFiles = BinFiles , Exefiles
-AddReg = GPACReg
-CEShortcuts = Shortcut , ProgLink
-CESelfRegister=GPAX.dll
-
-[SourceDisksNames]
-
-1 =, "Common Files",, ..
-2 =, "Extra Files",, .
-
-[SourceDisksFiles]
-libgpac.dll = 1
-%ExeName% = 1
-GPAX.dll = 1
-
-;comment this one if not using SpiderMonkey
-js.dll = 1
-
-;uncomment if your device doesn't have GX installed (I think most do)
-;gx.dll = 2
-
-;all gpac modules - comment the ones you haven't compiled
-gm_aac_in.dll = 1
-gm_amr_dec.dll = 1
-;gm_amr_float_dec.dll = 1
-gm_bifs_dec.dll = 1
-gm_ctx_load.dll = 1
-gm_dummy_in.dll = 1
-;gm_ffmpeg_in.dll = 1
-gm_ft_font.dll = 1
-gm_gapi.dll = 1
-gm_img_in.dll = 1
-gm_isom_in.dll = 1
-gm_mp3_in.dll = 1
-gm_odf_dec.dll = 1
-gm_render2d.dll = 1
-gm_rtp_in.dll = 1
-gm_timedtext.dll = 1
-gm_soft_raster.dll = 1
-gm_wav_out.dll = 1
-gm_xvid_dec.dll = 1
-;gm_ogg_xiph.dll = 1
-
-;these 2 go together
-;gm_render3d.dll = 1
-;libGLES_CM.dll = 1
-
-;these 2 go together
-gm_svg_loader.dll = 1
-libxml2.dll = 1
-
-;==================================================
-
-
-
-; Ouput directories for files & shortcuts
-
-[DestinationDirs]
-BinFiles = 0, %CE2%
-Exefiles = 0, %InstallDir%
-Shortcut = 0, %CE17%
-ProgLink = 0, %CE11%
-DefaultDestDir = 0, %InstallDir%
-
-[BinFiles]
-;"gx.dll"
-"libgpac.dll"
-"GPAX.dll"
-"js.dll"
-"libGLES_CM.dll"
-;"libxml2.dll"
-
-
-[Exefiles]
-"gm_aac_in.dll"
-"gm_amr_dec.dll"
-;"gm_amr_float_dec.dll"
-"gm_bifs_dec.dll"
-"gm_ctx_load.dll"
-"gm_dummy_in.dll"
-;"gm_ffmpeg_in.dll"
-"gm_ft_font.dll"
-"gm_gapi.dll"
-"gm_img_in.dll"
-"gm_isom_in.dll"
-"gm_mp3_in.dll"
-"gm_odf_dec.dll"
-"gm_render2d.dll"
-"gm_rtp_in.dll"
-"gm_soft_raster.dll"
-"gm_timedtext.dll"
-"gm_wav_out.dll"
-"gm_xvid_dec.dll"
-;"gm_ogg_xiph.dll"
-
-"gm_render3d.dll"
-
-;"gm_svg_loader.dll"
-
-[GPACReg]
-;GPAC cfg file location
-HKCR,GPAC,InstallDir,0x00000000,%InstallDir%
-
-;UDP socket overwrite
-HKLM,Comm\Afd,DgramBuffer,0x00010001,16
-;GPAC cfg file association
-HKCR,.cfg,,0x00000000,txtfile
-;MP4 file association
-HKCR,.mp4,,0x00000000,mp4file
-HKCR,mp4file\Shell\Open\Command,,0x00000000,"""%InstallDir%\%ExeName%""" """%%L"""
-;Icon number is bin ID of ressource in app
-HKCR,mp4file\DefaultIcon,,0x00000000,"%InstallDir%\%ExeName%,-128"
-
-[Shortcut]
-"%AppName%", 0, "%ExeName%"
-
-[ProgLink]
-"AppName", 0, "%ExeName%"
-
+++ /dev/null
-[CEAppManager]
-Version = 1.0
-Component = GPAC for PocketPC 2002
-
-[GPAC for PocketPC 2002]
-Description = GPAC Osmo4
-Uninstall = GPAC Osmo4
-IconFile = ..\..\w32_rel\Osmo4.ico
-IconIndex = 0
-CabFiles = GPAC.cab
+++ /dev/null
-This will install Osmo4 / GPAC version 0.4.2 for PocketPC/SmartPhone 2002
-
-GPAC is an open source MPEG-4 framework developped by ENST and available at:
- http://gpac.sourceforge.net
-
-WARNING: THIS RELEASE COMES WITH NO WARRANTY, AND MAY EVEN DAMAGE YOUR HANDHELD DEVICE. PLEASE READ CAREFULLY THE LICENSE HEREJOIN
+++ /dev/null
-CabWiz gpac.inf
-ezsetup -l english -i gpac.ini -r readme.txt -e ../../../COPYING -o GPAC_0.4.5_Setup_arm_ppc03.exe
-del *.cab
-del *.dat
+++ /dev/null
-[Version]
-Signature = "$Windows NT$"
-Provider = "GPAC 0.4.5"
-CESignature = "$Windows CE$"
-
-[CEStrings]
-;Osmo4 for PocketPC install, Osmophone for Smartphone install
-AppName = Osmophone
-InstallDir = \Program Files\GPAC
-
-[Strings]
-;Osmo4.exe for PocketPC install, Osmophone.exe for Smartphone install
-ExeName = Osmophone.exe
-
-[DefaultInstall]
-CopyFiles = BinFiles , Exefiles
-AddReg = GPACReg
-CEShortcuts = Shortcut , ProgLink
-CESelfRegister=GPAX.dll
-
-
-[SourceDisksNames]
-
-1 =, "Common Files",, ..
-2 =, "Extra Files",, .
-3 =, "Doc Files",, ..\..\..\doc\
-
-[SourceDisksFiles]
-libgpac.dll = 1
-%ExeName% = 1
-;Osmo4.exe = 1
-GPAX.dll = 1
-gpac.mp4 = 3
-
-;comment this one if not using OpenGL
-libGLES_CM.dll = 1
-
-;comment this one if not using SpiderMonkey
-js.dll = 1
-
-;uncomment if your device doesn't have GX installed (I think most do)
-;gx.dll = 2
-
-;all gpac modules - comment the ones you haven't compiled
-gm_aac_in.dll = 1
-gm_amr_dec.dll = 1
-;gm_amr_float_dec.dll = 1
-gm_bifs_dec.dll = 1
-gm_ctx_load.dll = 1
-gm_dummy_in.dll = 1
-gm_ffmpeg_in.dll = 1
-gm_ft_font.dll = 1
-gm_gapi.dll = 1
-gm_img_in.dll = 1
-gm_ismacryp.dll = 1
-gm_isom_in.dll = 1
-gm_laser_dec.dll = 1
-gm_mp3_in.dll = 1
-gm_odf_dec.dll = 1
-gm_rtp_in.dll = 1
-gm_timedtext.dll = 1
-gm_soft_raster.dll = 1
-gm_svg_in.dll = 1
-gm_wav_out.dll = 1
-gm_xvid_dec.dll = 1
-;gm_ogg_xiph.dll = 1
-
-
-;ENST Proprietary modules
-;gm_upnp.dll = 1
-
-;==================================================
-
-
-
-; Ouput directories for files & shortcuts
-
-[DestinationDirs]
-BinFiles = 0, %CE2%
-Exefiles = 0, %InstallDir%
-Shortcut = 0, %CE17%
-ProgLink = 0, %CE11%
-DefaultDestDir = 0, %InstallDir%
-
-[BinFiles]
-;"gx.dll"
-"libgpac.dll"
-"GPAX.dll"
-"js.dll"
-"libGLES_CM.dll"
-;"libxml2.dll"
-
-[Exefiles]
-"%ExeName%"
-;"Osmo4.exe"
-"gpac.mp4"
-"gm_aac_in.dll"
-"gm_amr_dec.dll"
-;"gm_amr_float_dec.dll"
-"gm_bifs_dec.dll"
-"gm_ctx_load.dll"
-"gm_dummy_in.dll"
-"gm_ffmpeg_in.dll"
-"gm_ft_font.dll"
-"gm_gapi.dll"
-"gm_img_in.dll"
-"gm_ismacryp.dll"
-"gm_isom_in.dll"
-"gm_laser_dec.dll"
-"gm_mp3_in.dll"
-"gm_odf_dec.dll"
-"gm_rtp_in.dll"
-"gm_soft_raster.dll"
-"gm_svg_in.dll"
-"gm_timedtext.dll"
-"gm_wav_out.dll"
-"gm_xvid_dec.dll"
-;"gm_ogg_xiph.dll"
-
-;"gm_upnp.dll"
-
-[GPACReg]
-;GPAC cfg file location
-HKCR,GPAC,InstallDir,0x00000000,%InstallDir%
-
-;GPAC cfg file association
-HKCR,.cfg,,0x00000000,txtfile
-
-;MP4 file association
-HKCR,.mp4,,0x00000000,mp4file
-HKCR,mp4file\Shell\Open\Command,,0x00000000,"""%InstallDir%\%ExeName%""" """%%L"""
-
-;Icon number is bin ID of ressource in app
-HKCR,mp4file\DefaultIcon,,0x00000000,"%InstallDir%\%ExeName%,-128"
-
-[Shortcut]
-"%AppName%", 0, "%ExeName%"
-
-[ProgLink]
-"%AppName%", 0, "%ExeName%"
-
+++ /dev/null
-[CEAppManager]
-Version = 1.0
-Component = GPAC for PocketPC 2003
-
-[GPAC for PocketPC 2003]
-Description = GPAC PocketPC MPEG-4 Player
-Uninstall = GPAC Osmo4
-IconFile = ..\..\w32_rel\Osmo4.ico
-IconIndex = 0
-CabFiles = GPAC.cab
+++ /dev/null
-This will install GPAC version 0.4.5 for ARM PocketPC/SmartPhones 2003 Platforms
-
-GPAC is an open source MPEG-4 framework developped by ENST and available at:
- http://gpac.sourceforge.net
-
-WARNING: THIS RELEASE COMES WITH NO WARRANTY, AND MAY EVEN DAMAGE YOUR HANDHELD DEVICE. PLEASE READ CAREFULLY THE LICENSE HEREJOIN
disable_loader_bt="no"
disable_loader_xmt="no"
disable_od_dump="no"
+disable_isom_dump="no"
disable_mcrypt="no"
disable_isoff="no"
disable_isoff_write="no"
--disable-vrml disable MPEG-4/VRML/X3D
--disable-x3d disable X3D only
--disable-odf disable full support of MPEG-4 OD Framework
- --disable-bifs disable BIFS coder
+ --disable-bifs disable BIFS
+ --disable-bifs-enc disable BIFS coder
--disable-laser disable LASeR coder
--disable-beng disable scene encoder engine
--disable-qtvr disable import of Cubic QTVR files
--disable-swf disable SWF import
--disable-scene-stats disable scene graph statistics
--disable-scene-dump disable scene graph dump
- --disable-od-dump disable OD dump
- --disable-mcrypt disable mcrypt
--disable-scene-encode disable BIFS & LASeR to ISO File Format encoding
--disable-loader-isoff disable scene loading from ISO File Format
--disable-loader-bt disable scene loading from ISO File Format
--disable-loader-xmt disable scene loading from ISO File Format
+ --disable-od-dump disable OD dump
+ --disable-isom-dump disable ISOM dump
+ --disable-mcrypt disable mcrypt
--disable-isoff disable ISO File Format
--disable-isoff-write disable ISO File Format edit/write
--disable-isoff-hint disable ISO File Format hinting
;;
--source-path=*) source_path=`echo $opt | cut -d '=' -f 2`
;;
- --cross-prefix=*) cross_prefix=`echo $opt | cut -d '=' -f 2` && echo "cross-prefix detected: $cross_prefix"
+ --cross-prefix=*) cross_prefix=`echo $opt | cut -d '=' -f 2` && echo "\ncross-prefix detected: $cross_prefix"
;;
--cc=*) cc=`echo $opt | cut -d '=' -f 2`
;;
#check pkg_config
-if ! $pkg_config --version >/dev/null 2>&1 ; then
- echo "$pkg_config not found, configure may detect wrong libraries"
+if test "$cross_prefix" = "" ; then
+ if ! $pkg_config --version >/dev/null 2>&1 ; then
+ echo "$pkg_config not found, configure may detect wrong libraries"
+ fi
fi
Linux)
js_flags="-DXP_UNIX -I/usr/include/js"
- LDFLAGS="$LDFLAGS -Wl,--warn-common"
+ LDFLAGS="$LDFLAGS -Wl,--warn-common -Wl,-z,defs"
#OSS_LDFLAGS="-laoss"
linux="yes"
case "$cpu" in
#GCC opt
if test "$no_gcc_opt" = "no"; then
- if $cc --version | grep 'sbox-arm-linux-gcc (GCC) 3.4.4'
- then
- echo "Detected buggy arm GCC (diablo), using -O2"
- CFLAGS="-O2 $CFLAGS"
- else
- CFLAGS="-O3 $CFLAGS"
- fi
+ CFLAGS="-O3 $CFLAGS"
+else
+ CFLAGS="-O0 $CFLAGS"
fi
fi
fi
+new_js_api="no"
if test "$has_js" != "no" ; then
js_flags="-DSPIDERMONKEY_NEW_API $js_flags"
- echo "SpiderMonkey new API detected" # (version > 1.8.0rc1)
+ new_js_api="yes"
fi
#spidermonkey test for regular API
fi
-
if test "$has_js" != "no" ; then
if test "$linux" = "yes" ; then
if test "$cpu" != "sh4"; then
-
#WARNING: there is a bug in MOZJS packages, the MOZILLA_1_8_BRANCH macro is not signaled, there is no way of knowing
#if the lib has been compiled with or without the macro. We currently just decide that if the macro is present
#in the header, it was enabled in the build
- if grep "MOZILLA_1_8_BRANCH" $js_inc/jsapi.h > /dev/null 2>&1 ; then
- js_flags="-DMOZILLA_1_8_BRANCH $js_flags"
- echo "WARNING: Turning on MOZILLA_1_8_BRANCH SpiderMonkey macro"
- echo "If you have troubles with scripts in GPAC, disable this macro and recompile"
+ if test "$new_js_api" = "no" ; then
+ if grep MOZILLA_1_8_BRANCH $js_inc/jsapi.h > /dev/null 2>&1 ; then
+ js_flags="-DMOZILLA_1_8_BRANCH $js_flags"
+ echo "WARNING: Turning on MOZILLA_1_8_BRANCH SpiderMonkey macro"
+ echo "If you have troubles with scripts in GPAC, disable this macro and recompile"
+ fi
+ else
+ #check presence of ***RuntimeThread
+ if grep RuntimeThread $js_inc/jsapi.h > /dev/null 2>&1 ; then
+ js_flags="$js_flags"
+ else
+ js_flags="-DNO_JS_RUNTIMETHREAD $js_flags"
+ fi
fi
-
fi
fi
fi
#include <Platinum.h>
int main( void ) { return 0; }
EOF
-if $cpp -o $TMPO $TMPC -I$local_inc/platinum $LDFLAGS -L$local_lib -lPlatinum -lPltMediaServer -lPltMediaConnect -lPltMediaRenderer -lNeptune -lZlib 2> /dev/null ; then
+if $cpp -o $TMPO $TMPC -I$local_inc/platinum $LDFLAGS -L$local_lib -lPlatinum -lPltMediaServer -lPltMediaConnect -lPltMediaRenderer -lNeptune -lZlib -lpthread 2> /dev/null ; then
has_platinum="yes"
fi
DeviceDescriptor* dd = 0;
for (DeviceCollector::DeviceList::const_iterator i = dl.begin(); i != dl.end(); i++) {
dd = *i;
- std::cout << dd->getName().c_str() << "\n";
+ std::cout << dd->getName().c_str() << "\n";
}
return 0;
}
avcap_ldflags="-lavcap -lpthread"
fi
if $cpp -o $TMPO $TMPC $avcap_cflags $LDFLAGS -L$local_lib $avcap_ldflags 2> /dev/null ; then
- has_avcap="yes"
+ has_avcap="yes"
avcap_ldflags="-L../../$local_lib $avcap_ldflags"
fi
fi
-#look for MAD support
+#look for FREENECT support
+freenect_flags=""
+freenect_ld="-lfreenect"
+
+if $pkg_config --exists libfreenect 2> /dev/null ; then
+ freenect_flags=`$pkg_config --cflags libfreenect`
+ freenect_libs=`$pkg_config --libs libfreenect`
+ has_freenect="system"
+ freenect_flags="-DFREENECT_FLAT_HEADERS $freenect_flags"
+
+else
+
has_freenect="no"
cat > $TMPC << EOF
#include <libfreenect/libfreenect.h>
elif test "$alt_macosx_dir" != "" ; then
if $cc -o $TMPO $TMPC -I$alt_macosx_dir/include -L$alt_macosx_dir/lib $LDFLAGS -lfreenect 2> /dev/null ; then
has_freenect="system"
+ freenect_flags=-I$alt_macosx_dir/include
+ freenect_ld=-L$alt_macosx_dir/lib -lfreenect
fi
fi
fi
if test "$has_freenect" = "no" ; then
- if $cc -o $TMPO $TMPC -I$local_inc/mad -L$local_lib -lfreenect 2> /dev/null ; then
+ if $cc -o $TMPO $TMPC -I$local_inc/freenect -L$local_lib -lfreenect 2> /dev/null ; then
has_freenect="local"
+ freenect_flags=-I$local_inc/freenect
+ freenect_ld=-L$local_lib -lfreenect
fi
fi
+fi
+
#look for vorbis support
cat > $TMPC << EOF
#look for OSS support
if test "$darwin" = "yes" ; then
+
cat > $TMPC << EOF
#include <soundcard.h>
int main( void ) { return 0; }
EOF
if $cc -o $TMPO $TMPC -DLIBOSS_INTERNAL -I$alt_macosx_dir/include/ -I$alt_macosx_dir/include/liboss -L$alt_macosx_dir/lib -loss $LDFLAGS 2> /dev/null ; then
- has_oss_audio="SYS"
+ has_oss_audio="yes"
OSS_CFLAGS="-DLIBOSS_INTERNAL -I$alt_macosx_dir/include/ -I$alt_macosx_dir/include/liboss"
OSS_LDFLAGS="-L$alt_macosx_dir/lib -loss"
fi
EOF
if $cc -o $TMPO $TMPC 2> /dev/null ; then
- has_oss_audio="SYS"
+ has_oss_audio="yes"
else
cat > $TMPC << EOF
#include <sys/ioctl.h>
EOF
if $cc -o $TMPO $TMPC $LDFLAGS 2> /dev/null ; then
- has_oss_audio="YES"
+ has_oss_audio="yes"
fi
fi
has_wx="no"
wx_too_old="no"
-if type wx-config >/dev/null 2>&1; then
+if test "$cross_prefix" = "" ; then
+ if type wx-config >/dev/null 2>&1; then
- wx_version=`wx-config --version | sed 's/[^0-9]//g'`
+ wx_version=`wx-config --version | sed 's/[^0-9]//g'`
- if test "$wx_version" -lt 250 ; then
- wx_too_old="yes"
- has_wx="yes"
- else
- if test "$wx_version" -lt 260 ; then
+ if test "$wx_version" -lt 250 ; then
+ wx_too_old="yes"
has_wx="yes"
- wx_cflags=`wx-config --cppflags`
- wx_lflags=`wx-config --libs`
else
- has_wx="yes"
- wx_cflags=`wx-config --cppflags core, base`
- wx_lflags=`wx-config --libs core, base`
- fi
+ if test "$wx_version" -lt 260 ; then
+ has_wx="yes"
+ wx_cflags=`wx-config --cppflags`
+ wx_lflags=`wx-config --libs`
+ else
+ has_wx="yes"
+ wx_cflags=`wx-config --cppflags core, base`
+ wx_lflags=`wx-config --libs core, base`
+ fi
- if test "$darwin" = "yes" ; then
- wx_lflags="-Wl,-bind_at_load $wx_lflags -lstdc++" #10.4 needs it, not sure about 10.3
+ if test "$darwin" = "yes" ; then
+ wx_lflags="-Wl,-bind_at_load $wx_lflags -lstdc++" #10.4 needs it, not sure about 10.3
+ fi
fi
- fi
-
- cat > $TMPCPP << EOF
+ cat > $TMPCPP << EOF
#include <wx/wx.h>
int main( void ) { return 0; }
EOF
- if $cc $wx_cflags -o $TMPO $TMPCPP $wx_lflags > /dev/null 2>&1 ; then
- wx_version=`wx-config --version | sed 's/[^0-9]//g'`
- if test "$wx_version" -lt 254 ; then
- wx_too_old="yes"
- else
- has_wx="yes"
+ if $cc $wx_cflags -o $TMPO $TMPCPP $wx_lflags > /dev/null 2>&1 ; then
+ wx_version=`wx-config --version | sed 's/[^0-9]//g'`
+ if test "$wx_version" -lt 254 ; then
+ wx_too_old="yes"
+ else
+ has_wx="yes"
+ fi
fi
fi
-
fi
#end wx test
--enable-pulseaudio=*) has_pulseaudio="yes"
;;
- --disable-all) has_pulseaudio="no"; has_alsa="no"; disable_3d="yes"; disable_svg="yes"; disable_vrml="yes"; disable_od="yes"; disable_bifs="yes"; disable_bifs_enc="yes"; disable_laser="yes"; disable_beng="yes"; disable_qtvr="yes"; disable_avi="yes"; disable_ogg="yes"; disable_m2ps="yes"; disable_m2ts="yes"; disable_m2ts_mux="yes"; disable_parsers="yes"; disable_import="yes"; disable_export="yes"; disable_swf="yes"; disable_scene_stats="yes"; disable_scene_dump="yes"; disable_scene_encode="yes"; disable_loader_isoff="yes"; disable_od_dump="yes"; disable_mcrypt="yes"; disable_isoff="yes"; disable_isoff_write="yes"; disable_isoff_hint="yes"; disable_isoff_frag="yes"; disable_streaming="yes"; disable_x3d="yes"; disable_loader_bt="yes"; disable_loader_xmt="yes"; has_dvb4linux="no"
+ --disable-all) has_pulseaudio="no"; has_alsa="no"; disable_3d="yes"; disable_svg="yes"; disable_vrml="yes"; disable_od="yes"; disable_bifs="yes"; disable_bifs_enc="yes"; disable_laser="yes"; disable_beng="yes"; disable_qtvr="yes"; disable_avi="yes"; disable_ogg="yes"; disable_m2ps="yes"; disable_m2ts="yes"; disable_m2ts_mux="yes"; disable_parsers="yes"; disable_import="yes"; disable_export="yes"; disable_swf="yes"; disable_scene_stats="yes"; disable_scene_dump="yes"; disable_scene_encode="yes"; disable_loader_isoff="yes"; disable_od_dump="yes"; disable_isom_dump="yes"; disable_mcrypt="yes"; disable_isoff="yes"; disable_isoff_write="yes"; disable_isoff_hint="yes"; disable_isoff_frag="yes"; disable_streaming="yes"; disable_x3d="yes"; disable_loader_bt="yes"; disable_loader_xmt="yes"; has_dvb4linux="no"
;;
--disable-3d) disable_3d="yes"
;;
--enable-od-dump) disable_od_dump="no"
;;
+ --disable-isom-dump) disable_isom_dump="yes"
+ ;;
+ --enable-isom-dump) disable_isom_dump="no"
+ ;;
--disable-mcrypt) disable_mcrypt="yes"
;;
--enable-mcrypt) disable_mcrypt="no"
sdl_static="yes"
fi
-if type $sdl_config >/dev/null 2>&1; then
- cat > $TMPC << EOF
+if test "$cross_prefix" = "" ; then
+ if type $sdl_config >/dev/null 2>&1; then
+
+ cat > $TMPC << EOF
#include <SDL.h>
#undef main
int main( void ) { return SDL_Init (SDL_INIT_VIDEO); }
EOF
- if test "$sdl_static" = "yes"; then
- sdl_lib_flags=`$sdl_config --static-libs`
- else
- sdl_lib_flags=`$sdl_config --libs`
- fi
- sdl_cflags=`$sdl_config --cflags`
-
- if $cc -o $TMPO $sdl_cflags $TMPC $LDFLAGS $sdl_lib_flags > /dev/null 2>&1 ; then
- _sdlversion=`$sdl_config --version | sed 's/[^0-9]//g'`
- if test "$_sdlversion" -lt 121 ; then
- sdl_too_old=yes
+ if test "$sdl_static" = "yes"; then
+ sdl_lib_flags=`$sdl_config --static-libs`
else
- has_sdl=yes
+ sdl_lib_flags=`$sdl_config --libs`
fi
- fi
+ sdl_cflags=`$sdl_config --cflags`
+ if $cc -o $TMPO $sdl_cflags $TMPC $LDFLAGS $sdl_lib_flags > /dev/null 2>&1 ; then
+ _sdlversion=`$sdl_config --version | sed 's/[^0-9]//g'`
+ if test "$_sdlversion" -lt 121 ; then
+ sdl_too_old=yes
+ else
+ has_sdl=yes
+ fi
+ fi
+ fi
fi
#end SDL check
echo "#define GPAC_CONFIGURATION \"$GPAC_CONFIGURATION\"" >> $TMPH
version="`grep '#define GPAC_VERSION ' \"$source_path/include/gpac/tools.h\" | cut -d '"' -f 2`"
+version_major=`grep '#define GPAC_VERSION_MAJOR ' $source_path/include/gpac/tools.h | sed -e 's/.*\([0-9]\)\+$/\1/'`
+version_minor=`grep '#define GPAC_VERSION_MINOR ' $source_path/include/gpac/tools.h | sed -e 's/.*\([0-9]\)\+$/\1/'`
+version_micro=`grep '#define GPAC_VERSION_MICRO ' $source_path/include/gpac/tools.h | sed -e 's/.*\([0-9]\)\+$/\1/'`
+soname_version="${version_major}.${version_minor}.${version_micro}"
if which svnversion >/dev/null
then
echo "OD dump disabled"
echo "#define GPAC_DISABLE_OD_DUMP" >> $TMPH
fi
+if test "$disable_isom_dump" = "yes" ; then
+ echo "ISOM dump disabled"
+ echo "#define GPAC_DISABLE_ISOM_DUMP" >> $TMPH
+fi
if test "$disable_mcrypt" = "yes" ; then
echo "MCrypt disabled"
echo "#define GPAC_DISABLE_MCRYPT" >> $TMPH
echo "Renoir enabled - make sure the driver libraries are present in modules/viren_out directory"
fi
-echo ""
if test "$has_amr_nb_fixed" = "yes" ; then
+ echo ""
echo "*** AMR NB FIXED-POINT NOTICE ***"
echo "Make sure you have downloaded TS26.073 from:"
echo "http://www.3gpp.org/ftp/Specs/archive/26_series/26.073/26073-*.zip"
echo ""
fi
-echo ""
if test "$has_amr_nb" = "yes" ; then
+ echo ""
echo "*** AMR NB NOTICE ***"
echo "Make sure you have downloaded TS26.104 from:"
echo "http://www.3gpp.org/ftp/Specs/archive/26_series/26.104/26104-*.zip"
fi
-echo ""
if test "$has_amr_wb" = "yes" ; then
+ echo ""
echo "*** AMR WB NOTICE ***"
echo "Make sure you have downloaded TS26.204 from:"
echo "http://www.3gpp.org/ftp/Specs/archive/26_series/26.204/26204-*.zip"
echo ""
fi
+echo ""
if test "$use_memory_tracking" = "yes"; then
echo "!! WARNING: GPAC Memory tracking is enabled !!"
echo "!! This may corrupt third-party tools using libgpac !!"
fi
echo "EXTRALIBS=$extralibs" >> config.mak
echo "VERSION=$version" >>config.mak
+echo "VERSION_MAJOR=$version_major" >>config.mak
+echo "VERSION_SONAME=$soname_version" >>config.mak
if test "$use_fixed_point" = "yes"; then
echo "#define GPAC_FIXED_POINT" >> $TMPH
echo "CONFIG_A52=$has_a52" >> config.mak
echo "CONFIG_PULSEAUDIO=$has_pulseaudio" >> config.mak
echo "CONFIG_FREENECT=$has_freenect" >> config.mak
+if test "$has_freenect" != "no"
+then
+ echo "FREENECT_CFLAGS=$freenect_flags" >> config.mak
+ echo "FREENECT_LDLAGS=$freenect_ld" >> config.mak
+fi
echo "DISABLE_SVG=$disable_svg" >> config.mak
+echo "DISABLE_LOADER_BT=$disable_loader_bt" >> config.mak
echo "HAS_LIBXML2=$has_libxml2" >> config.mak
if test "$has_libxml2" = "yes"; then
echo "XML2_CFLAGS=$libxml2_cflags" >> config.mak
echo "XML2_LIBS=$libxml2_lib_flags" >> config.mak
fi
-
+if test "$disable_m2ts_mux" = "yes" -o "$disable_m2ts" = "yes" ; then
+ echo "DISABLE_M2TS=yes" >> config.mak
+fi
echo "GPAC_USE_TINYGL=$has_tinygl" >> config.mak
echo "OGL_INCLS=$INCL3D" >> config.mak
-echo "DISABLE_ISOFF=$disable_isoff" >> config.mak
+if test "$disable_isoff" = "yes" -o "$disable_isoff_write" = "yes" ; then
+ echo "DISABLE_ISOFF=$disable_isoff" >> config.mak
+fi
echo "HAS_OPENGL=$has_opengl" >> config.mak
#ifndef _GF_AIT_H_\r
#define _GF_AIT_H_\r
\r
-#ifndef GPAC_DISABLE_MPEG2TS\r
-\r
#ifdef __cplusplus\r
extern "C" {\r
#endif\r
#include <gpac/bitstream.h>\r
\r
\r
+#ifndef GPAC_DISABLE_MPEG2TS\r
+\r
+\r
#define AIT_SECTION_LENGTH_MAX 1021\r
#define APPLICATION_TYPE_HTTP_APPLICATION 16\r
#define DSMCC_SECTION_LENGTH_MAX 4093\r
GF_M2TS_CHANNEL_APPLICATION_INFO* gf_m2ts_get_channel_application_info(GF_List* ChannelAppList, u32 ait_service_id);\r
void gf_m2ts_delete_channel_application_info(GF_M2TS_CHANNEL_APPLICATION_INFO* ChannelApp);\r
\r
+#endif /*GPAC_DISABLE_MPEG2TS*/\r
+\r
#ifdef __cplusplus\r
}\r
#endif\r
-#endif\r
\r
#endif //_GF_CAROUSSEL_H_\r
\r
#ifndef _GF_DSMCC_H_\r
#define _GF_DSMCC_H_\r
\r
-#ifndef GPAC_DISABLE_MPEG2TS\r
-\r
-\r
#ifdef __cplusplus\r
extern "C" {\r
#endif\r
#include <string.h>\r
#include <gpac/bitstream.h>\r
\r
+\r
+#ifndef GPAC_DISABLE_MPEG2TS\r
+\r
+\r
#define DSMCC_SECTION_LENGTH_MAX 4093\r
\r
typedef enum{\r
Bool get_index;\r
/* Number of the application that uses the carousel*/\r
u32 application_id;\r
-}GF_M2TS_DSMCC_OVERLORD;\r
+} GF_M2TS_DSMCC_OVERLORD;\r
\r
void on_dsmcc_section(GF_M2TS_Demuxer *ts, u32 evt_type, void *par);\r
GF_Err gf_m2ts_process_dsmcc(GF_M2TS_DSMCC_OVERLORD* dsmcc_overlord,GF_M2TS_DSMCC_SECTION *dsmcc, char *data, u32 data_size, u32 table_id);\r
GF_M2TS_DSMCC_OVERLORD* gf_m2ts_get_dmscc_overlord(GF_List* Dsmcc_controller,u32 service_id);\r
void gf_m2ts_delete_dsmcc_overlord(GF_M2TS_DSMCC_OVERLORD* dsmcc_overlord);\r
\r
+#endif /*GPAC_DISABLE_MPEG2TS*/\r
+\r
#ifdef __cplusplus\r
}\r
#endif\r
-#endif\r
\r
#endif //_GF_CAROUSSEL_H_\r
\r
GF_OMADRMAUFormatBox *fmt;
} GF_OMADRMKMSBox;
-#ifndef GPAC_DISABLE_ISOM_FRAGMENTS
typedef struct
{
u32 nb_refs;
GF_SIDXReference *refs;
} GF_SegmentIndexBox;
-#endif
GF_Err subs_Read(GF_Box *s, GF_BitStream *bs);
GF_Err subs_dump(GF_Box *a, FILE * trace);
+#ifndef GPAC_DISABLE_ISOM_FRAGMENTS
GF_Box *tfdt_New();
void tfdt_del(GF_Box *);
GF_Err tfdt_Write(GF_Box *s, GF_BitStream *bs);
GF_Err tfdt_Size(GF_Box *s);
GF_Err tfdt_Read(GF_Box *s, GF_BitStream *bs);
GF_Err tfdt_dump(GF_Box *a, FILE * trace);
+#endif
GF_Box *rvcc_New();
void rvcc_del(GF_Box *);
#define SMJS_FREE(__c, __str) if (__str) JS_free(__c, __str)
-#define SMJS_OBJ_CONSTRUCTOR JSObject *obj = NULL;\
- if (!JS_IsConstructing_PossiblyWithGivenThisObject(c, argsvp, &obj)) { \
- return JS_FALSE;\
- }\
- if (obj == NULL) obj = JS_NewObjectForConstructor(c, argsvp); \
+#define SMJS_OBJ_CONSTRUCTOR \
+ JSObject *obj = JS_NewObjectForConstructor(c, argsvp); \
SMJS_SET_RVAL(OBJECT_TO_JSVAL(obj));\
#define JS_GetFunctionName(_v) (JS_GetFunctionId(_v)!=NULL) ? SMJS_CHARS_FROM_STRING(c, JS_GetFunctionId(_v)) : NULL
if end_range>start_range, restricts the URL to the given byterange when parsing*/
GF_Err gf_isom_open_segment(GF_ISOFile *movie, const char *fileName, u64 start_range, u64 end_range);
-#ifndef GPAC_DISBALE_ISOM_FRAGMENTS
+#ifndef GPAC_DISABLE_ISOM_FRAGMENTS
/*
Movie Fragments Writing API
void gf_isom_reset_fragment_info(GF_ISOFile *movie);
-#endif /*GPAC_DISBALE_ISOM_FRAGMENTS*/
+#endif /*GPAC_DISABLE_ISOM_FRAGMENTS*/
/******************************************************************
/*creates (if needed) a GF_ESD for the given track - THIS IS RESERVED for local playback
only, since the OTI used when emulated is not standard...*/
GF_ESD *gf_media_map_esd(GF_ISOFile *mp4, u32 track);
+
#endif
/*adds chapter info contained in file - import_fps is optional (most formats don't use it), defaults to 25*/
GF_Err gf_media_import_chapters(GF_ISOFile *file, char *chap_file, Double import_fps);
-
-/*save file as fragmented movie
-@dash_mode: 0 = DASH not used, 1 = DASH used without GOP spliting, 2 = DASH used with GOP spliting, */
-GF_Err gf_media_fragment_file(GF_ISOFile *input, const char *output_file_radical, const char *mpd_name, Double max_duration_sec, u32 dash_mode, Double dash_duration_sec, char *seg_rad_name, char *seg_ext, s32 subsegs_per_sidx, Bool daisy_chain_sidx, Bool use_url_template, Bool use_single_segment, const char *dash_ctx, GF_ISOFile *sample_descs, u32 rep_id);
-
/*make the file ISMA compliant: creates ISMA BIFS / OD tracks if needed, and update audio/video IDs
the file should not contain more than one audio and one video track
@keepImage: if set, generates system info if image is found - only used for image imports
*/
GF_Err gf_media_make_psp(GF_ISOFile *mp4file);
-/*changes pixel aspect ratio for visual tracks if supported. Negative values remove any PAR info*/
-GF_Err gf_media_change_par(GF_ISOFile *file, u32 track, s32 ar_num, s32 ar_den);
-
/*changes the profile (if not 0) and level (if not 0) indication of the media - only AVC/H264 supported for now*/
GF_Err gf_media_change_pl(GF_ISOFile *file, u32 track, u32 profile, u32 level);
#endif /*GPAC_DISABLE_MEDIA_IMPORT*/
+/*changes pixel aspect ratio for visual tracks if supported. Negative values remove any PAR info*/
+GF_Err gf_media_change_par(GF_ISOFile *file, u32 track, s32 ar_num, s32 ar_den);
+
+
+#ifndef GPAC_DISABLE_ISOM_WRITE
+
+/*starts MPD file */
+GF_Err gf_media_mpd_start(char *mpd_name, char *title, Bool use_url_template, Bool single_segment, char *dash_ctx, GF_ISOFile *init_segment, Double period_duration);
+GF_Err gf_media_mpd_end(char *mpd_name);
+
+#ifndef GPAC_DISABLE_ISOM_FRAGMENTS
+/*save file as fragmented movie
+@dash_mode: 0 = DASH not used, 1 = DASH used without GOP spliting, 2 = DASH used with GOP spliting, */
+GF_Err gf_media_fragment_file(GF_ISOFile *input, const char *output_file_radical, const char *mpd_name, Double max_duration_sec, u32 dash_mode, Double dash_duration_sec, char *seg_rad_name, char *seg_ext, s32 subsegs_per_sidx, Bool daisy_chain_sidx, Bool use_url_template, Bool use_single_segment, const char *dash_ctx, GF_ISOFile *sample_descs, u32 rep_id);
+#endif
+
+#endif
+
#ifndef GPAC_DISABLE_MEDIA_EXPORT
GF_Err gf_saf_mux_for_time(GF_SAFMuxer *mux, u32 time_ms, Bool force_end_of_session, char **out_data, u32 *out_size);
-GF_Err gf_media_mpd_start(char *mpd_name, char *title, Bool use_url_template, Bool single_segment, char *dash_ctx, char *init_segment, Double period_duration);
-GF_Err gf_media_mpd_end(char *mpd_name);
#ifdef __cplusplus
}
#include <gpac/ietf.h>
#include <gpac/isomedia.h>
-#ifndef GPAC_DISABLE_STREAMING
+#if !defined(GPAC_DISABLE_STREAMING) && !defined(GPAC_DISABLE_ISOM)
typedef struct __rtp_streamer GF_RTPStreamer;
}
#endif
-#endif //GPAC_DISABLE_STREAMING
+#endif //GPAC_DISABLE_ISOM && GPAC_DISABLE_STREAMING
#endif /*_GF_RTPSTREAMER_H_*/
# ifndef GPAC_DISABLE_MPEG2PS
# define GPAC_DISABLE_MPEG2PS
# endif
+# ifndef GPAC_DISABLE_ISOM_HINTING
+# define GPAC_DISABLE_ISOM_HINTING
+# endif
+# ifndef GPAC_DISABLE_MEDIA_IMPORT
+# define GPAC_DISABLE_MEDIA_IMPORT
+# endif
+# ifndef GPAC_DISABLE_MPEG2TS_MUX
+# define GPAC_DISABLE_MPEG2TS_MUX
+# endif
#endif
#ifdef GPAC_DISABLE_ISOM
# ifndef GPAC_DISABLE_ISOM_DUMP
# define GPAC_DISABLE_ISOM_DUMP
# endif
+# ifndef GPAC_DISABLE_LOADER_ISOM
+# define GPAC_DISABLE_LOADER_ISOM
+# endif
+# ifndef GPAC_DISABLE_MEDIA_EXPORT
+# define GPAC_DISABLE_MEDIA_EXPORT
+# endif
#endif
#ifdef GPAC_DISABLE_ISOM_WRITE
# ifndef GPAC_DISABLE_MEDIA_IMPORT
# define GPAC_DISABLE_MEDIA_IMPORT
# endif
+# ifndef GPAC_DISABLE_QTVR
+# define GPAC_DISABLE_QTVR
+# endif
+# ifndef GPAC_DISABLE_ISOM_HINTING
+# define GPAC_DISABLE_ISOM_HINTING
+# endif
+# ifndef GPAC_DISABLE_SCENE_ENCODER
+# define GPAC_DISABLE_SCENE_ENCODER
+# endif
#endif
#ifdef GPAC_DISABLE_STREAMING
*
* Macro giving GPAC version expressed as a printable string
*/
-/*KEEP SPACE SEPARATORS FOR MAKE / GREP (SEE MAIN MAKEFILE)!!!, and NO SPACE in GPAC_VERSION for proper install*/
-#define GPAC_VERSION "0.4.6-DEV"
+/* KEEP SPACE SEPARATORS FOR MAKE / GREP (SEE MAIN MAKEFILE)
+ * NO SPACE in GPAC_VERSION for proper install
+ * SONAME versions must be digits (not strings)
+ */
+#define GPAC_VERSION "0.4.6-DEV"
+#define GPAC_VERSION_MAJOR 1
+#define GPAC_VERSION_MINOR 1
+#define GPAC_VERSION_MICRO 0
#include <gpac/version.h>
#define GPAC_FULL_VERSION GPAC_VERSION"-rev"GPAC_SVN_REVISION
include ../config.mak
#all OS and lib independent
-PLUGDIRS=aac_in ac3_in audio_filter bifs_dec ctx_load dummy_in soft_raster mp3_in isom_in odf_dec rtp_in timedtext img_in svg_in saf_in mpegts_in ismacryp widgetman mpd_in osd
+PLUGDIRS=aac_in ac3_in audio_filter bifs_dec ctx_load dummy_in soft_raster mp3_in isom_in odf_dec rtp_in timedtext img_in svg_in saf_in mpegts_in ismacryp mpd_in
ifeq ($(DISABLE_SVG), no)
-PLUGDIRS+=laser_dec svg_in
+PLUGDIRS+=laser_dec svg_in widgetman
+ifeq ($(DISABLE_LOADER_BT),no)
+PLUGDIRS+=osd
+endif
endif
ifeq ($(CONFIG_FT), no)
DDCONTEXT;
opt = gf_modules_get_option((GF_BaseInterface *)dr, "Video", "HardwareMemory");
- if (use_system_memory) {
- if (opt && !strcmp(opt, "Always")) use_system_memory = 0;
- } else {
- if (opt && !strcmp(opt, "Never")) use_system_memory = 1;
+ if (opt) {
+ if (use_system_memory) {
+ if (!strcmp(opt, "Always")) use_system_memory = 0;
+ } else {
+ if (!strcmp(opt, "Never")) use_system_memory = 1;
+ else if (!strcmp(opt, "Auto")) dd->force_video_mem_for_yuv = 1;
+ }
}
force_reinit = 0;
return GF_OK;
}
+
GF_Err InitDirectDraw(GF_VideoOutput *dr, u32 Width, u32 Height)
{
HRESULT hr;
ddraw->lpVtbl->Release(ddraw);
if (FAILED(hr)) return GF_IO_ERR;
+
dd->switch_res = 0;
cooplev = DDSCL_NORMAL;
/*Setup FS*/
return GF_IO_ERR;
}
pcClipper->lpVtbl->Release(pcClipper);
+
dd->ddraw_init = 1;
/*if YUV not initialize, init using HW video memory to setup HW caps*/
return CreateBackBuffer(dr, Width, Height, dd->yuv_init);
if (key) flags |= DDBLT_KEYSRC;
hr = dd->pBack->lpVtbl->Blt(dd->pBack, dst_wnd ? &r_dst : NULL, src->pSurface, src_wnd ? &r_src : NULL, flags, NULL);
}
+
+ if (src->is_yuv && dd->force_video_mem_for_yuv && dd->systems_memory) return GF_IO_ERR;
+
GF_LOG(GF_LOG_DEBUG, GF_LOG_MMIO, ("[DX Out] Hardware blit src w=%d,h=%d to dst w=%d,h=%d - result: %08x\n", src_w, src_h, dst_w, dst_h, hr));
return FAILED(hr) ? GF_IO_ERR : GF_OK;
}
SAFE_DD_RELEASE(yuvp->pSurface);
memset(yuvp, 0, sizeof(DDSurface));
+ yuvp->is_yuv = 1;
memset (&ddsd, 0, sizeof(ddsd));
ddsd.dwSize = sizeof(ddsd);
if (dd->yuv_pool.pSurface) {
SAFE_DD_RELEASE(dd->yuv_pool.pSurface);
memset(&dd->yuv_pool, 0, sizeof(DDSurface));
+ dd->yuv_pool.is_yuv = 1;
}
dr->yuv_pixel_format = formats[i];
if (dd->yuv_pool.pSurface) {
SAFE_DD_RELEASE(dd->yuv_pool.pSurface);
memset(&dd->yuv_pool, 0, sizeof(DDSurface));
+ dd->yuv_pool.is_yuv = 1;
}
if (best_planar && (min_planar <= min_packed )) {
{
LPDDRAWSURFACE pSurface;
u32 width, height, format, pitch;
+ Bool is_yuv;
} DDSurface;
Bool windowless, hidden;
Bool dd_lost;
-
+ Bool force_video_mem_for_yuv;
HMODULE hDDrawLib;
DIRECTDRAWCREATEPROC DirectDrawCreate;
-
} DDContext;
void DD_SetupWindow(GF_VideoOutput *dr, Bool hide);
memset(&dd->rgb_pool, 0, sizeof(DDSurface));
SAFE_DD_RELEASE(dd->yuv_pool.pSurface);
memset(&dd->yuv_pool, 0, sizeof(DDSurface));
+ dd->yuv_pool.is_yuv = 1;
SAFE_DD_RELEASE(dd->pPrimary);
SAFE_DD_RELEASE(dd->pBack);
static const char *FFDEC_GetCodecName(GF_BaseDecoder *dec)
{
FFDec *ffd;
- if (!dec)
- return NULL;
- ffd = dec->privateStack;
+ if (!dec)
+ return NULL;
+ ffd = dec->privateStack;
if (ffd && ffd->base_codec) {
sprintf(ffd->szCodec, "FFMPEG %s", ffd->base_codec->name ? ffd->base_codec->name : "unknown");
return ffd->szCodec;
FFDec *priv;
/* Note for valgrind : those two functions cause a leak in valgrind */
- GF_LOG(GF_LOG_INFO, GF_LOG_CONTAINER, ("[FFMPEG Decoder] Registering all ffmpeg codecs...\n") );
+ GF_LOG(GF_LOG_INFO, GF_LOG_CONTAINER, ("[FFMPEG Decoder] Registering all ffmpeg codecs...\n") );
+#ifdef FF_API_AVCODE_INIT /*commit ffmpeg 3211932c513338566b31d990d06957e15a644d13*/
avcodec_init();
+#endif
avcodec_register_all();
- GF_LOG(GF_LOG_DEBUG, GF_LOG_CONTAINER, ("[FFMPEG Decoder] Done registering all ffmpeg codecs.\n") );
+ GF_LOG(GF_LOG_DEBUG, GF_LOG_CONTAINER, ("[FFMPEG Decoder] Done registering all ffmpeg codecs.\n") );
GF_SAFEALLOC(ptr , GF_MediaDecoder);
pkt.stream_index = -1;
/*EOF*/
- if (av_read_frame(ffd->ctx, &pkt) <0) break;
+ if (av_read_frame(ffd->ctx, &pkt) <0) break;
if (pkt.pts == AV_NOPTS_VALUE) pkt.pts = pkt.dts;
if (!pkt.dts) pkt.dts = pkt.pts;
Bool ret = 0;
char *ext, szName[1000], szExt[20];
const char *szExtList;
- if (!plug || !url)
- return 0;
+ if (!plug || !url)
+ return 0;
/*disable RTP/RTSP from ffmpeg*/
if (!strnicmp(url, "rtsp://", 7)) return 0;
if (!strnicmp(url, "rtspu://", 8)) return 0;
/*figure out if we can use codecs or not*/
has_video = has_audio = 0;
- for(i = 0; i < (s32)ctx->nb_streams; i++) {
- AVCodecContext *enc = ctx->streams[i]->codec;
- switch(enc->codec_type) {
- case AVMEDIA_TYPE_AUDIO:
- if (!has_audio) has_audio = 1;
- break;
- case AVMEDIA_TYPE_VIDEO:
- if (!has_video) has_video= 1;
- break;
- default:
- break;
- }
- }
+ for(i = 0; i < (s32)ctx->nb_streams; i++) {
+ AVCodecContext *enc = ctx->streams[i]->codec;
+ switch(enc->codec_type) {
+ case AVMEDIA_TYPE_AUDIO:
+ if (!has_audio) has_audio = 1;
+ break;
+ case AVMEDIA_TYPE_VIDEO:
+ if (!has_video) has_video= 1;
+ break;
+ default:
+ break;
+ }
+ }
if (!has_audio && !has_video) goto exit;
ret = 1;
#if LIBAVFORMAT_VERSION_MAJOR < 53 && LIBAVFORMAT_VERSION_MINOR < 45
/*remap std object types - depending on input formats, FFMPEG may not have separate DSI from initial frame.
In this case we have no choice but using FFMPEG decoders*/
if (for_audio) {
- AVCodecContext *dec = ffd->ctx->streams[ffd->audio_st]->codec;
+ AVCodecContext *dec = ffd->ctx->streams[ffd->audio_st]->codec;
esd->slConfig->timestampResolution = ffd->audio_tscale.den;
- switch (dec->codec_id) {
+ switch (dec->codec_id) {
case CODEC_ID_MP2:
esd->decoderConfig->objectTypeIndication = GPAC_OTI_AUDIO_MPEG1;
break;
}
dont_use_sl = ffd->unreliable_audio_timing;
} else {
- AVCodecContext *dec = ffd->ctx->streams[ffd->video_st]->codec;
+ AVCodecContext *dec = ffd->ctx->streams[ffd->video_st]->codec;
esd->slConfig->timestampResolution = ffd->video_tscale.den;
switch (dec->codec_id) {
case CODEC_ID_MPEG4:
GF_LOG(GF_LOG_DEBUG, GF_LOG_CONTAINER, ("[FFMPEG] opening file %s - local %d - av_in %08x\n", url, is_local, av_in));
if (!is_local) {
- AVProbeData pd;
+ AVProbeData pd;
/*setup wraper for FFMPEG I/O*/
ffd->buffer_size = 8192;
#ifdef FFMPEG_DUMP_REMOTE
ffd->outdbg = gf_f64_open("ffdeb.raw", "wb");
#endif
-/*#ifdef USE_PRE_0_7*/
- init_put_byte(&ffd->io, ffd->buffer, ffd->buffer_size, 0, ffd, ff_url_read, NULL, NULL);
-/*#else
- ffio_init_context(&ffd->io, ffd->buffer, ffd->buffer_size, 0, ffd, ff_url_read, NULL, NULL);
-#endif*/
#ifdef USE_PRE_0_7
+ init_put_byte(&ffd->io, ffd->buffer, ffd->buffer_size, 0, ffd, ff_url_read, NULL, NULL);
ffd->io.is_streamed = 1;
#else
ffd->io.seekable = 1;
}
/*setup downloader*/
av_in->flags |= AVFMT_NOFILE;
+#if FF_API_FORMAT_PARAMETERS /*commit ffmpeg 603b8bc2a109978c8499b06d2556f1433306eca7*/
+ res = avformat_open_input(&ffd->ctx, szName, av_in, NULL);
+#else
res = av_open_input_stream(&ffd->ctx, &ffd->io, szName, av_in, NULL);
+#endif
}
} else {
res = open_file(&ffd->ctx, szName, av_in);
/*figure out if we can use codecs or not*/
ffd->audio_st = ffd->video_st = -1;
- for (i = 0; i < ffd->ctx->nb_streams; i++) {
- AVCodecContext *enc = ffd->ctx->streams[i]->codec;
- switch(enc->codec_type) {
- case AVMEDIA_TYPE_AUDIO:
- if ((ffd->audio_st<0) && (ffd->service_type!=1)) {
+ for (i = 0; i < ffd->ctx->nb_streams; i++) {
+ AVCodecContext *enc = ffd->ctx->streams[i]->codec;
+ switch(enc->codec_type) {
+ case AVMEDIA_TYPE_AUDIO:
+ if ((ffd->audio_st<0) && (ffd->service_type!=1)) {
ffd->audio_st = i;
ffd->audio_tscale = ffd->ctx->streams[i]->time_base;
}
- break;
- case AVMEDIA_TYPE_VIDEO:
- if ((ffd->video_st<0) && (ffd->service_type!=2)) {
+ break;
+ case AVMEDIA_TYPE_VIDEO:
+ if ((ffd->video_st<0) && (ffd->service_type!=2)) {
ffd->video_st = i;
ffd->video_tscale = ffd->ctx->streams[i]->time_base;
}
- break;
- default:
- break;
- }
- }
+ break;
+ default:
+ break;
+ }
+ }
if ((ffd->service_type==1) && (ffd->video_st<0)) goto err_exit;
if ((ffd->service_type==2) && (ffd->audio_st<0)) goto err_exit;
if ((ffd->video_st<0) && (ffd->audio_st<0)) {
char szURL[2048], *sep;
FFDemux *ffd;
const char *this_url;
- if (!plug || !url)
- return 0;
- ffd = (FFDemux *)plug->priv;
- this_url = gf_term_get_service_url(ffd->service);
+ if (!plug || !url)
+ return 0;
+ ffd = (FFDemux *)plug->priv;
+ this_url = gf_term_get_service_url(ffd->service);
if (!this_url)
- return 0;
+ return 0;
strcpy(szURL, this_url);
sep = strrchr(szURL, '#');
{
FFDemux *ffd;
GF_InputService *ptr = (GF_InputService *)ifce;
- if (!ptr)
- return;
+ if (!ptr)
+ return;
ffd = ptr->priv;
- if (ffd){
- if (ffd->thread)
- gf_th_del(ffd->thread);
- ffd->thread = NULL;
- if (ffd->mx)
- gf_mx_del(ffd->mx);
- ffd->mx = NULL;
- gf_free(ffd);
- ptr->priv = NULL;
- }
+ if (ffd) {
+ if (ffd->thread)
+ gf_th_del(ffd->thread);
+ ffd->thread = NULL;
+ if (ffd->mx)
+ gf_mx_del(ffd->mx);
+ ffd->mx = NULL;
+ gf_free(ffd);
+ ptr->priv = NULL;
+ }
gf_free(ptr);
}
#include <gpac/constants.h>
#include <gpac/download.h>
+#ifdef FREENECT_FLAT_HEADERS
+#include <libfreenect.h>
+#else
#include <libfreenect/libfreenect.h>
+#endif
#include <gpac/thread.h>
+
+#ifndef FREENECT_RESOLUTION_MEDIUM
+#define FREENECT_MINIMAL
+#endif
+
+
typedef struct
{
/*the service we're responsible for*/
if (!vcap->f_ctx) {
int i;
- Bool use_depth = 1;
+#ifndef FREENECT_MINIMAL
freenect_frame_mode frame_mode;
freenect_resolution frame_format = FREENECT_RESOLUTION_MEDIUM;
+#endif
char *name, *params;
int res = freenect_init(&vcap->f_ctx, NULL);
if (res < 0) {
}
freenect_set_log_level(vcap->f_ctx, FREENECT_LOG_DEBUG);
freenect_set_log_callback(vcap->f_ctx, Freenect_Logs);
+#ifndef FREENECT_MINIMAL
freenect_select_subdevices(vcap->f_ctx, FREENECT_DEVICE_CAMERA);
-
+#endif
res = freenect_num_devices (vcap->f_ctx);
GF_LOG(GF_LOG_INFO, GF_LOG_MODULE, ("[Freenect] %d devices found\n", res));
if (res<1) {
if (name) name += 3;
if (!stricmp(name, "color")) {
- use_depth = 0;
}
if (params) {
GF_LOG(GF_LOG_INFO, GF_LOG_MODULE, ("[VideoCapture] Set camera option %s\n", params));
if (!strnicmp(params, "resolution=", 11)) {
+#ifndef FREENECT_MINIMAL
u32 w, h;
if (sscanf(params+11, "%dx%d", &w, &h)==2) {
if ((w<=320) || (h<=240)) frame_format = FREENECT_RESOLUTION_LOW;
else if ((w<=640) || (h<=480)) frame_format = FREENECT_RESOLUTION_MEDIUM;
else frame_format = FREENECT_RESOLUTION_HIGH;
}
+#endif
}
else if (!strnicmp(params, "format=", 7)) {
if (!stricmp(params+7, "standard")) vcap->depth_format = 0;
params = sep+1;
}
+#ifndef FREENECT_MINIMAL
frame_mode = freenect_find_video_mode(frame_format, FREENECT_VIDEO_RGB);
res = freenect_set_video_mode(vcap->f_dev, frame_mode);
res = freenect_set_depth_mode(vcap->f_dev, freenect_find_depth_mode(frame_format, FREENECT_DEPTH_11BIT));
-
vcap->width = frame_mode.width;
vcap->height = frame_mode.height;
vcap->fps = frame_mode.framerate;
+#else
+ freenect_set_video_format(vcap->f_dev, FREENECT_VIDEO_RGB);
+ res = freenect_set_depth_format(vcap->f_dev, FREENECT_DEPTH_11BIT);
+ vcap->width = FREENECT_FRAME_W;
+ vcap->height = FREENECT_FRAME_H;
+ vcap->fps = 30;
+#endif
/*currently hardcoded*/
vcap->color_pixel_format = GF_PIXEL_RGB_24;
vcap->color_stride = 3*vcap->width;
res = freenect_set_video_buffer(vcap->f_dev, vcap->vid_buf);
- GF_LOG(GF_LOG_INFO, GF_LOG_MODULE, ("[Freenect]Â Device configured - resolution %dx%d - Frame Rate %d - Depth Pixel Format %s\n", vcap->width, vcap->height, vcap->fps, gf_4cc_to_str(vcap->depth_pixel_format) ));
+ GF_LOG(GF_LOG_INFO, GF_LOG_MODULE, ("[Freenect] Device configured - resolution %dx%d - Frame Rate %d - Depth Pixel Format %s\n", vcap->width, vcap->height, vcap->fps, gf_4cc_to_str(vcap->depth_pixel_format) ));
for (i=0; i<2048; i++) {
*vp = INT_TO_JSVAL(evt->type);
break;
case 1:
+#ifndef GPAC_DISABLE_SVG
*vp = STRING_TO_JSVAL(JS_NewStringCopyZ(c, gf_dom_get_key_name(evt->key.key_code) ));
+#endif
break;
case 2:
*vp = INT_TO_JSVAL(evt->mouse.x);
SMJS_ARGS
GF_GPACJSExt *gjs = (GF_GPACJSExt *)JS_GetPrivate(c, obj);
if (!argc || !JSVAL_IS_OBJECT(argv[0])) return JS_FALSE;
- if (gjs->evt_fun) return JS_TRUE;
+ if (JSVAL_IS_NULL(gjs->evt_fun) ) return JS_TRUE;
gjs->evt_fun = argv[0];
gjs->evt_filter_obj = obj;
if (!elt) return JS_TRUE;
switch (elt->sgprivate->tag) {
case TAG_MPEG4_Inline:
+#ifndef GPAC_DISABLE_X3D
case TAG_X3D_Inline:
+#endif
scene = (GF_Scene *)gf_node_get_private(elt);
break;
+#ifndef GPAC_DISABLE_SVG
case TAG_SVG_animation:
sg = gf_sc_animation_get_scenegraph(elt);
scene = (GF_Scene *)gf_sg_get_private(sg);
break;
+#endif
default:
return JS_TRUE;
}
gf_isom_sample_del(&ch->sample);
if (s2 && s1) {
+ assert(s2->DTS >= s1->DTS);
time_diff = (u32) (s2->DTS - s1->DTS);
e = gf_isom_get_sample_for_movie_time(ch->owner->mov, ch->track, ch->sample_time + time_diff, &ivar, GF_ISOM_SEARCH_FORWARD, &ch->sample, &ch->sample_num);
} else if (s1 && !s2) {
/* 0 not started, 1 download in progress */
MPD_STATE mpd_is_running;
Bool mpd_stop_request;
-
+ Bool in_period_setup;
/* TODO - handle playback status for SPEED/SEEK through SIDX */
Double playback_speed, playback_start_range, previous_start_range;
+ Double start_range_in_segment_at_next_period;
Bool in_seek;
} GF_MPD_In;
void MPD_ResetGroups(GF_MPD_In *mpdin);
GF_Err MPD_SetupPeriod(GF_MPD_In *mpdin);
-void MPD_SeekGroupsDownloads(GF_MPD_In *mpdin);
+
static const char *MPD_GetMimeType(GF_MPD_SubRepresentation *subrep, GF_MPD_Representation *rep, GF_MPD_AdaptationSet *set)
return GF_OK;
}
if (param->command_type==GF_NET_SERVICE_QUERY_NEXT) {
+ Bool discard_first_cache_entry = 1;
u32 timer = gf_sys_clock();
GF_LOG(GF_LOG_DEBUG, GF_LOG_MODULE, ("[MPD_IN] Received Service Query Next request from terminal\n"));
gf_mx_p(mpdin->dl_mutex);
if (mpdin->in_seek) {
mpdin->in_seek = 0;
param->url_query.discontinuity_type = 2;
+ discard_first_cache_entry = 0;
}
for (i=0; i<gf_list_count(mpdin->groups); i++) {
while (mpdin->mpd_is_running && group->nb_cached_segments<2) {
gf_mx_v(mpdin->dl_mutex);
if (group->done) {
- if (!mpdin->request_period_switch && (mpdin->active_period_index<gf_list_count(mpdin->mpd->periods))) {
+ if (!mpdin->request_period_switch && (mpdin->active_period_index+1 < gf_list_count(mpdin->mpd->periods))) {
GF_NetworkCommand com;
memset(&com, 0, sizeof(GF_NetworkCommand));
com.command_type = GF_NET_BUFFER_QUERY;
}
gf_sleep(20);
}
- }
+ }
return GF_EOS;
}
gf_sleep(16);
} else {
GF_LOG(GF_LOG_DEBUG, GF_LOG_MODULE, ("[MPD_IN] Had to wait for %u ms for the only cache file to be downloaded\n", (gf_sys_clock() - timer)));
}
- if (group->cached[0].cache) {
- if (group->urlToDeleteNext) {
- if (!group->local_files && !mpdin->keep_files)
- gf_dm_delete_cached_file_entry_session(group->segment_dnload, group->urlToDeleteNext);
- gf_free( group->urlToDeleteNext);
- group->urlToDeleteNext = NULL;
- }
- assert( group->cached[0].url );
- GF_LOG(GF_LOG_DEBUG, GF_LOG_MODULE, ("[MPD_IN] deleting cache file %s : %s\n", group->cached[0].url, group->cached[0].cache));
- group->urlToDeleteNext = gf_strdup( group->cached[0].url );
- gf_free(group->cached[0].cache);
- gf_free(group->cached[0].url);
- group->cached[0].url = NULL;
- group->cached[0].cache = NULL;
- }
- memmove(&group->cached[0], &group->cached[1], sizeof(segment_cache_entry)*(group->nb_cached_segments-1));
- memset(&(group->cached[group->nb_cached_segments-1]), 0, sizeof(segment_cache_entry));
- group->nb_cached_segments--;
+ if (discard_first_cache_entry) {
+ if (group->cached[0].cache) {
+ if (group->urlToDeleteNext) {
+ if (!group->local_files && !mpdin->keep_files)
+ gf_dm_delete_cached_file_entry_session(group->segment_dnload, group->urlToDeleteNext);
+
+ gf_free( group->urlToDeleteNext);
+ group->urlToDeleteNext = NULL;
+ }
+ assert( group->cached[0].url );
+ GF_LOG(GF_LOG_DEBUG, GF_LOG_MODULE, ("[MPD_IN] deleting cache file %s : %s\n", group->cached[0].url, group->cached[0].cache));
+ group->urlToDeleteNext = gf_strdup( group->cached[0].url );
+ gf_free(group->cached[0].cache);
+ gf_free(group->cached[0].url);
+ group->cached[0].url = NULL;
+ group->cached[0].cache = NULL;
+ }
+ memmove(&group->cached[0], &group->cached[1], sizeof(segment_cache_entry)*(group->nb_cached_segments-1));
+ memset(&(group->cached[group->nb_cached_segments-1]), 0, sizeof(segment_cache_entry));
+ group->nb_cached_segments--;
+ }
+
param->url_query.next_url = group->cached[0].cache;
param->url_query.start_range = group->cached[0].start_range;
param->url_query.end_range = group->cached[0].end_range;
}
}
-static void MPD_SetGroupRepresentation(GF_MPD_Group *group, GF_MPD_Representation *rep)
+static void MPD_GetSegmentDuration(GF_MPD_Representation *rep, GF_MPD_AdaptationSet *set, GF_MPD_Period *period, GF_MPD *mpd, u32 *nb_segments, Double *seg_duration)
{
- u64 duration = 0;
- u64 mediaDuration = 0;
-#ifndef GPAC_DISABLE_LOG
- u32 width=0, height=0, samplerate=0;
- GF_MPD_Fractional *framerate=NULL;
-#endif
- u32 timescale = 1;
- GF_MPD_AdaptationSet *set;
- GF_MPD_Period *period;
- u32 i = gf_list_find(group->adaptation_set->representations, rep);
- assert((s32) i >= 0);
-
- group->active_rep_index = i;
- group->active_bitrate = rep->bandwidth;
- group->nb_segments_in_rep = 1;
-
- set = group->adaptation_set;
- period = group->period;
-
-#ifndef GPAC_DISABLE_LOG
-
-#define GET_REP_ATTR(_a) _a = rep->_a; if (!_a) _a = set->_a;
-
- GET_REP_ATTR(width);
- GET_REP_ATTR(height);
- GET_REP_ATTR(samplerate);
- GET_REP_ATTR(framerate);
-
- GF_LOG(GF_LOG_INFO, GF_LOG_MODULE, ("[MPDIn] Switched to representation bandwidth %d kbps\n", rep->bandwidth/1024));
- if (group->max_bitrate) GF_LOG(GF_LOG_INFO, GF_LOG_MODULE, ("\tmax download bandwidth: %d kbps\n", group->max_bitrate/1024));
- if (width&&height) {
- GF_LOG(GF_LOG_INFO, GF_LOG_MODULE, ("\tWidth %d Height %d", width, height));
- if (framerate) GF_LOG(GF_LOG_INFO, GF_LOG_MODULE, ("framerate %d/%d", framerate->num, framerate->den));
- GF_LOG(GF_LOG_INFO, GF_LOG_MODULE, ("\n"));
- } else if (samplerate) {
- GF_LOG(GF_LOG_INFO, GF_LOG_MODULE, ("\tsamplerate %d\n", samplerate));
- }
-#endif
-
+ Double mediaDuration;
+ u32 timescale;
+ u64 duration;
+ *nb_segments = timescale = 0;
+ duration = 0;
+
/*single segment*/
if (rep->segment_base || set->segment_base || period->segment_base) {
return;
if (rep->segment_list->segment_URLs) segments = rep->segment_list->segment_URLs;
}
if (segments)
- group->nb_segments_in_rep = gf_list_count(segments);
+ *nb_segments = gf_list_count(segments);
- if (!timescale) timescale=1;
- group->segment_duration = (Double) duration;
- group->segment_duration /= timescale;
+ if (! timescale) timescale=1;
+ *seg_duration = (Double) duration;
+ *seg_duration /= timescale;
return;
}
if (rep->segment_template->timescale) timescale = rep->segment_template->timescale;
}
if (!timescale) timescale=1;
- group->segment_duration = (Double) duration;
- group->segment_duration /= timescale;
+ *seg_duration = (Double) duration;
+ *seg_duration /= timescale;
mediaDuration = period->duration;
- if (!mediaDuration) mediaDuration = group->mpd_in->mpd->media_presentation_duration;
+ if (!mediaDuration) mediaDuration = mpd->media_presentation_duration;
if (mediaDuration && duration) {
Double nb_seg = (Double) mediaDuration;
/*duration is given in ms*/
nb_seg /= 1000;
nb_seg *= timescale;
nb_seg /= duration;
- group->nb_segments_in_rep = (u32) ceil(nb_seg);
- } else {
- group->nb_segments_in_rep = 0;
+ *nb_segments = (u32) ceil(nb_seg);
}
}
+
+static void MPD_SetGroupRepresentation(GF_MPD_Group *group, GF_MPD_Representation *rep)
+{
+ u64 duration = 0;
+ u64 mediaDuration = 0;
+#ifndef GPAC_DISABLE_LOG
+ u32 width=0, height=0, samplerate=0;
+ GF_MPD_Fractional *framerate=NULL;
+#endif
+ u32 timescale = 1;
+ GF_MPD_AdaptationSet *set;
+ GF_MPD_Period *period;
+ u32 i = gf_list_find(group->adaptation_set->representations, rep);
+ assert((s32) i >= 0);
+
+ group->active_rep_index = i;
+ group->active_bitrate = rep->bandwidth;
+ group->nb_segments_in_rep = 1;
+
+ set = group->adaptation_set;
+ period = group->period;
+
+#ifndef GPAC_DISABLE_LOG
+
+#define GET_REP_ATTR(_a) _a = rep->_a; if (!_a) _a = set->_a;
+
+ GET_REP_ATTR(width);
+ GET_REP_ATTR(height);
+ GET_REP_ATTR(samplerate);
+ GET_REP_ATTR(framerate);
+
+ GF_LOG(GF_LOG_INFO, GF_LOG_MODULE, ("[MPDIn] Switched to representation bandwidth %d kbps\n", rep->bandwidth/1024));
+ if (group->max_bitrate) GF_LOG(GF_LOG_INFO, GF_LOG_MODULE, ("\tmax download bandwidth: %d kbps\n", group->max_bitrate/1024));
+ if (width&&height) {
+ GF_LOG(GF_LOG_INFO, GF_LOG_MODULE, ("\tWidth %d Height %d", width, height));
+ if (framerate) GF_LOG(GF_LOG_INFO, GF_LOG_MODULE, ("framerate %d/%d", framerate->num, framerate->den));
+ GF_LOG(GF_LOG_INFO, GF_LOG_MODULE, ("\n"));
+ } else if (samplerate) {
+ GF_LOG(GF_LOG_INFO, GF_LOG_MODULE, ("\tsamplerate %d\n", samplerate));
+ }
+#endif
+
+
+ MPD_GetSegmentDuration(rep, set, period, group->mpd_in->mpd, &group->nb_segments_in_rep, &group->segment_duration);
+}
+
static void MPD_SwitchGroupRepresentation(GF_MPD_In *mpd, GF_MPD_Group *group)
{
u32 i, bandwidth, min_bandwidth;
gf_mx_v(mpdin->dl_mutex);
restart_period:
+ mpdin->in_period_setup = 1;
e = GF_OK;
period = gf_list_get(mpdin->mpd->periods, mpdin->active_period_index);
group_count = gf_list_count(mpdin->groups);
}
gf_mx_p(mpdin->dl_mutex);
+ mpdin->in_period_setup = 0;
mpdin->mpd_is_running = MPD_STATE_RUNNING;
gf_mx_v(mpdin->dl_mutex);
{
u32 i;
assert( mpdin );
- if (mpdin->groups){
- for (i=0; i<gf_list_count(mpdin->groups); i++) {
- GF_MPD_Group *group = gf_list_get(mpdin->groups, i);
- assert( group );
- if (group->selected && group->segment_dnload) {
- gf_dm_sess_abort(group->segment_dnload);
- group->done = 1;
+ if (mpdin->groups) {
+ for (i=0; i<gf_list_count(mpdin->groups); i++) {
+ GF_MPD_Group *group = gf_list_get(mpdin->groups, i);
+ assert( group );
+ if (! group->service_connected ) return;
+ if (group->selected && group->segment_dnload) {
+ gf_dm_sess_abort(group->segment_dnload);
+ group->done = 1;
+ }
}
- }
}
/* stop the download thread */
gf_mx_p(mpdin->dl_mutex);
u32 i, period_idx;
gf_mx_p(mpdin->dl_mutex);
+
+ mpdin->start_range_in_segment_at_next_period = 0;
start_time = 0;
period_idx = 0;
for (i=0; i<=gf_list_count(mpdin->mpd->periods); i++) {
mpdin->playback_start_range -= start_time;
mpdin->active_period_index = period_idx;
mpdin->request_period_switch = 2;
+
+ /*figure out default segment duration and substract from our start range request*/
+ if (mpdin->playback_start_range) {
+ Double duration;
+ u32 nb_segs;
+ GF_MPD_Period *period = gf_list_get(mpdin->mpd->periods, period_idx);
+ GF_MPD_AdaptationSet *set = gf_list_get(period->adaptation_sets, 0);
+ GF_MPD_Representation *rep = gf_list_get(set->representations, 0);
+
+ MPD_GetSegmentDuration(rep, set, period, mpdin->mpd, &nb_segs, &duration);
+
+ if (duration) {
+ while (mpdin->playback_start_range - mpdin->start_range_in_segment_at_next_period >= duration)
+ mpdin->start_range_in_segment_at_next_period += duration;
+ }
+
+ }
}
gf_mx_v(mpdin->dl_mutex);
u32 first_downloaded, last_downloaded, segment_idx;
group->force_segment_switch = 0;
+ if (!group->segment_duration) return;
/*figure out where to seek*/
segment_idx = 0;
u32 i;
gf_mx_p(mpdin->dl_mutex);
+
+ if (mpdin->active_period_index) {
+ Double dur = 0;
+ u32 i;
+ for (i=0; i<mpdin->active_period_index; i++) {
+ GF_MPD_Period *period = gf_list_get(mpdin->mpd->periods, mpdin->active_period_index-1);
+ dur += period->duration/1000.0;
+ }
+ mpdin->playback_start_range -= dur;
+ }
for (i=0; i<gf_list_count(mpdin->groups); i++) {
GF_MPD_Group *group = gf_list_get(mpdin->groups, i);
MPD_SeekGroup(mpdin, group);
case GF_NET_CHAN_PLAY:
GF_LOG(GF_LOG_DEBUG, GF_LOG_MODULE, ("[MPD_IN] Received Play command from terminal on channel %p on Service (%p)\n", com->base.on_channel, mpdin->service));
- if (!com->play.dash_segment_switch && ! mpdin->in_seek) {
+ if (! mpdin->in_period_setup && !com->play.dash_segment_switch && ! mpdin->in_seek) {
Bool skip_seek;
mpdin->in_seek = 1;
else if (mpdin->in_seek && (com->play.start_range==0)) {
// mpdin->in_seek = 0;
}
+ else if (mpdin->in_period_setup && (com->play.start_range==0)) {
+ com->play.start_range = mpdin->playback_start_range;
+ }
+
group->done = 0;
com->play.dash_segment_switch = group->force_segment_switch;
/*don't forward commands, we are killing the service anyway ...*/
GF_OSD *osd;\r
dr = (GF_TermExt*)gf_malloc(sizeof(GF_TermExt));\r
memset(dr, 0, sizeof(GF_TermExt));\r
- GF_REGISTER_MODULE_INTERFACE(dr, GF_TERM_EXT_INTERFACE, "GPAC OnSscreen Display", "gpac distribution");\r
+ GF_REGISTER_MODULE_INTERFACE(dr, GF_TERM_EXT_INTERFACE, "GPAC OnScreen Display", "gpac distribution");\r
\r
GF_SAFEALLOC(osd, GF_OSD);\r
dr->process = osd_process;\r
LDFLAGS+=-pg
endif
-ifeq ($(OSS_INC_TYPE), SYS)
+ifeq ($(OSS_INC_TYPE), yes)
else
CFLAGS+=-DOSS_FIX_INC
endif
LDFLAGS+=-pg
endif
-LINKLIBS= -lgpac -lPlatinum -lPltMediaServer -lPltMediaConnect -lPltMediaRenderer -lNeptune -lZlib
+LINKLIBS= -lgpac -lPlatinum -lPltMediaServer -lPltMediaConnect -lPltMediaRenderer -lNeptune -lZlib -lpthread
LOCAL_LIB=../../bin/gcc -L../../extra_lib/lib/gcc
#common objects
--- /dev/null
+include ../../config.mak
+
+vpath %.c $(SRC_PATH)/modules/widgetman
+
+CFLAGS= $(OPTFLAGS) -I"$(SRC_PATH)/include"
+
+ifeq ($(DEBUGBUILD), yes)
+CFLAGS+=-g
+LDFLAGS+=-g
+endif
+
+ifeq ($(GPROFBUILD), yes)
+CFLAGS+=-pg
+LDFLAGS+=-pg
+endif
+
+LINKLIBS= -lgpac -lz
+LOCAL_LIB=-L../../bin/gcc
+
+#common objects
+OBJS=widgetman.o unzip.o widget.o wgt_load.o
+
+ifeq ($(CONFIG_ZLIB), local)
+CFLAGS+=-I"$(LOCAL_INC_PATH)/zlib"
+LOCAL_LIB+= -L../../extra_lib/lib/gcc
+endif
+
+ifeq ($(CONFIG_JS),no)
+else
+CFLAGS+=$(JS_FLAGS)
+ifeq ($(CONFIG_JS),local)
+NEED_LOCAL_LIB="yes"
+LOCAL_LIB+= -L../../extra_lib/lib/gcc
+endif
+LINKLIBS+= $(JS_LIBS)
+endif
+
+SRCS := $(OBJS:.o=.c)
+
+LIB=gm_widgetman.$(DYN_LIB_SUFFIX)
+ifeq ($(CONFIG_WIN32),yes)
+#LDFLAGS+=-export-symbols widgetman.def
+endif
+
+
+all: $(LIB)
+
+
+$(LIB): $(OBJS)
+ $(CC) $(SHFLAGS) $(LDFLAGS) -o ../../bin/gcc/$@ $(OBJS) $(EXTRALIBS) $(LOCAL_LIB) $(LINKLIBS)
+
+
+%.o: %.c
+ $(CC) $(CFLAGS) -c -o $@ $<
+
+
+clean:
+ rm -f $(OBJS) ../../bin/gcc/$(LIB)
+
+dep: depend
+
+depend:
+ rm -f .depend
+ $(CC) -MM $(CFLAGS) $(SRCS) 1>.depend
+
+distclean: clean
+ rm -f Makefile.bak .depend
+
+
+
+# include dependency files if they exist
+#
+ifneq ($(wildcard .depend),)
+include .depend
+endif
--- /dev/null
+/*
+ miniunz.c
+ Version 1.01e, February 12th, 2005
+
+ Copyright (C) 1998-2005 Gilles Vollant
+*/
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+
+#ifndef _WIN32_WCE
+#include <errno.h>
+#include <fcntl.h>
+
+#ifdef WIN32
+# include <direct.h>
+# include <io.h>
+#else
+# include <unistd.h>
+# include <utime.h>
+# include <sys/stat.h>
+#endif
+
+#endif
+
+#include "unzip.h"
+#include <gpac/tools.h>
+
+
+
+/* I've found an old Unix (a SunOS 4.1.3_U1) without all SEEK_* defined.... */
+
+#ifndef SEEK_CUR
+#define SEEK_CUR 1
+#endif
+
+#ifndef SEEK_END
+#define SEEK_END 2
+#endif
+
+#ifndef SEEK_SET
+#define SEEK_SET 0
+#endif
+
+voidpf ZCALLBACK fopen_file_func OF((
+ voidpf opaque,
+ const char* filename,
+ int mode));
+
+uLong ZCALLBACK fread_file_func OF((
+ voidpf opaque,
+ voidpf stream,
+ void* buf,
+ uLong size));
+
+uLong ZCALLBACK fwrite_file_func OF((
+ voidpf opaque,
+ voidpf stream,
+ const void* buf,
+ uLong size));
+
+long ZCALLBACK ftell_file_func OF((
+ voidpf opaque,
+ voidpf stream));
+
+long ZCALLBACK fseek_file_func OF((
+ voidpf opaque,
+ voidpf stream,
+ uLong offset,
+ int origin));
+
+int ZCALLBACK fclose_file_func OF((
+ voidpf opaque,
+ voidpf stream));
+
+int ZCALLBACK ferror_file_func OF((
+ voidpf opaque,
+ voidpf stream));
+
+
+voidpf ZCALLBACK fopen_file_func (opaque, filename, mode)
+ voidpf opaque;
+ const char* filename;
+ int mode;
+{
+ FILE* file = NULL;
+ const char* mode_fopen = NULL;
+ if ((mode & ZLIB_FILEFUNC_MODE_READWRITEFILTER)==ZLIB_FILEFUNC_MODE_READ)
+ mode_fopen = "rb";
+ else
+ if (mode & ZLIB_FILEFUNC_MODE_EXISTING)
+ mode_fopen = "r+b";
+ else
+ if (mode & ZLIB_FILEFUNC_MODE_CREATE)
+ mode_fopen = "wb";
+
+ if ((filename!=NULL) && (mode_fopen != NULL))
+ file = fopen(filename, mode_fopen);
+ return file;
+}
+
+
+uLong ZCALLBACK fread_file_func (opaque, stream, buf, size)
+ voidpf opaque;
+ voidpf stream;
+ void* buf;
+ uLong size;
+{
+ uLong ret;
+ ret = (uLong)fread(buf, 1, (size_t)size, (FILE *)stream);
+ return ret;
+}
+
+
+uLong ZCALLBACK fwrite_file_func (opaque, stream, buf, size)
+ voidpf opaque;
+ voidpf stream;
+ const void* buf;
+ uLong size;
+{
+ uLong ret;
+ ret = (uLong)gf_fwrite(buf, 1, (size_t)size, (FILE *)stream);
+ return ret;
+}
+
+long ZCALLBACK ftell_file_func (opaque, stream)
+ voidpf opaque;
+ voidpf stream;
+{
+ long ret;
+ ret = ftell((FILE *)stream);
+ return ret;
+}
+
+long ZCALLBACK fseek_file_func (opaque, stream, offset, origin)
+ voidpf opaque;
+ voidpf stream;
+ uLong offset;
+ int origin;
+{
+ int fseek_origin=0;
+ long ret;
+ switch (origin)
+ {
+ case ZLIB_FILEFUNC_SEEK_CUR :
+ fseek_origin = SEEK_CUR;
+ break;
+ case ZLIB_FILEFUNC_SEEK_END :
+ fseek_origin = SEEK_END;
+ break;
+ case ZLIB_FILEFUNC_SEEK_SET :
+ fseek_origin = SEEK_SET;
+ break;
+ default: return -1;
+ }
+ ret = 0;
+ fseek((FILE *)stream, offset, fseek_origin);
+ return ret;
+}
+
+int ZCALLBACK fclose_file_func (opaque, stream)
+ voidpf opaque;
+ voidpf stream;
+{
+ int ret;
+ ret = fclose((FILE *)stream);
+ return ret;
+}
+
+int ZCALLBACK ferror_file_func (opaque, stream)
+ voidpf opaque;
+ voidpf stream;
+{
+ int ret;
+ ret = ferror((FILE *)stream);
+ return ret;
+}
+
+void fill_fopen_filefunc (pzlib_filefunc_def)
+ zlib_filefunc_def* pzlib_filefunc_def;
+{
+ pzlib_filefunc_def->zopen_file = fopen_file_func;
+ pzlib_filefunc_def->zread_file = fread_file_func;
+ pzlib_filefunc_def->zwrite_file = fwrite_file_func;
+ pzlib_filefunc_def->ztell_file = ftell_file_func;
+ pzlib_filefunc_def->zseek_file = fseek_file_func;
+ pzlib_filefunc_def->zclose_file = fclose_file_func;
+ pzlib_filefunc_def->zerror_file = ferror_file_func;
+ pzlib_filefunc_def->opaque = NULL;
+}
+
+static int unzlocal_getByte(pzlib_filefunc_def,filestream,pi)
+ const zlib_filefunc_def* pzlib_filefunc_def;
+ voidpf filestream;
+ int *pi;
+{
+ unsigned char c;
+ int err = (int)ZREAD(*pzlib_filefunc_def,filestream,&c,1);
+ if (err==1)
+ {
+ *pi = (int)c;
+ return UNZ_OK;
+ }
+ else
+ {
+ if (ZERROR(*pzlib_filefunc_def,filestream))
+ return UNZ_ERRNO;
+ else
+ return UNZ_EOF;
+ }
+}
+
+static int unzlocal_getShort (pzlib_filefunc_def,filestream,pX)
+ const zlib_filefunc_def* pzlib_filefunc_def;
+ voidpf filestream;
+ uLong *pX;
+{
+ uLong x ;
+ int err;
+ int i = 0;
+
+ err = unzlocal_getByte(pzlib_filefunc_def,filestream,&i);
+ x = (uLong)i;
+
+ if (err==UNZ_OK)
+ err = unzlocal_getByte(pzlib_filefunc_def,filestream,&i);
+ x += ((uLong)i)<<8;
+
+ if (err==UNZ_OK)
+ *pX = x;
+ else
+ *pX = 0;
+ return err;
+}
+
+static int unzlocal_getLong (pzlib_filefunc_def,filestream,pX)
+ const zlib_filefunc_def* pzlib_filefunc_def;
+ voidpf filestream;
+ uLong *pX;
+{
+ uLong x ;
+ int err;
+ int i = 0;
+
+ err = unzlocal_getByte(pzlib_filefunc_def,filestream,&i);
+ x = (uLong)i;
+
+ if (err==UNZ_OK)
+ err = unzlocal_getByte(pzlib_filefunc_def,filestream,&i);
+ x += ((uLong)i)<<8;
+
+ if (err==UNZ_OK)
+ err = unzlocal_getByte(pzlib_filefunc_def,filestream,&i);
+ x += ((uLong)i)<<16;
+
+ if (err==UNZ_OK)
+ err = unzlocal_getByte(pzlib_filefunc_def,filestream,&i);
+ x += ((uLong)i)<<24;
+
+ if (err==UNZ_OK)
+ *pX = x;
+ else
+ *pX = 0;
+ return err;
+}
+
+static uLong unzlocal_SearchCentralDir(pzlib_filefunc_def,filestream)
+ const zlib_filefunc_def* pzlib_filefunc_def;
+ voidpf filestream;
+{
+ unsigned char* buf;
+ uLong uSizeFile;
+ uLong uBackRead;
+ uLong uMaxBack=0xffff; /* maximum size of global comment */
+ uLong uPosFound=0;
+
+ if (ZSEEK(*pzlib_filefunc_def,filestream,0,ZLIB_FILEFUNC_SEEK_END) != 0)
+ return 0;
+
+
+ uSizeFile = ZTELL(*pzlib_filefunc_def,filestream);
+
+ if (uMaxBack>uSizeFile)
+ uMaxBack = uSizeFile;
+
+ buf = (unsigned char*)ALLOC(BUFREADCOMMENT+4);
+ if (buf==NULL)
+ return 0;
+
+ uBackRead = 4;
+ while (uBackRead<uMaxBack)
+ {
+ uLong uReadSize,uReadPos ;
+ int i;
+ if (uBackRead+BUFREADCOMMENT>uMaxBack)
+ uBackRead = uMaxBack;
+ else
+ uBackRead+=BUFREADCOMMENT;
+ uReadPos = uSizeFile-uBackRead ;
+
+ uReadSize = ((BUFREADCOMMENT+4) < (uSizeFile-uReadPos)) ?
+ (BUFREADCOMMENT+4) : (uSizeFile-uReadPos);
+ if (ZSEEK(*pzlib_filefunc_def,filestream,uReadPos,ZLIB_FILEFUNC_SEEK_SET)!=0)
+ break;
+
+ if (ZREAD(*pzlib_filefunc_def,filestream,buf,uReadSize)!=uReadSize)
+ break;
+
+ for (i=(int)uReadSize-3; (i--)>0;)
+ if (((*(buf+i))==0x50) && ((*(buf+i+1))==0x4b) &&
+ ((*(buf+i+2))==0x05) && ((*(buf+i+3))==0x06))
+ {
+ uPosFound = uReadPos+i;
+ break;
+ }
+
+ if (uPosFound!=0)
+ break;
+ }
+ TRYFREE(buf);
+ return uPosFound;
+}
+
+
+/*
+ Translate date/time from Dos format to tm_unz (readable more easilty)
+*/
+void unzlocal_DosDateToTmuDate (ulDosDate, ptm)
+ uLong ulDosDate;
+ tm_unz* ptm;
+{
+ uLong uDate;
+ uDate = (uLong)(ulDosDate>>16);
+ ptm->tm_mday = (uInt)(uDate&0x1f) ;
+ ptm->tm_mon = (uInt)((((uDate)&0x1E0)/0x20)-1) ;
+ ptm->tm_year = (uInt)(((uDate&0x0FE00)/0x0200)+1980) ;
+
+ ptm->tm_hour = (uInt) ((ulDosDate &0xF800)/0x800);
+ ptm->tm_min = (uInt) ((ulDosDate&0x7E0)/0x20) ;
+ ptm->tm_sec = (uInt) (2*(ulDosDate&0x1f)) ;
+}
+
+static int unzlocal_GetCurrentFileInfoInternal (file,
+ pfile_info,
+ pfile_info_internal,
+ szFileName, fileNameBufferSize,
+ extraField, extraFieldBufferSize,
+ szComment, commentBufferSize)
+ unzFile file;
+ unz_file_info *pfile_info;
+ unz_file_info_internal *pfile_info_internal;
+ char *szFileName;
+ uLong fileNameBufferSize;
+ void *extraField;
+ uLong extraFieldBufferSize;
+ char *szComment;
+ uLong commentBufferSize;
+{
+ unz_s* s;
+ unz_file_info file_info;
+ unz_file_info_internal file_info_internal;
+ int err=UNZ_OK;
+ uLong uMagic;
+ long lSeek=0;
+
+ if (file==NULL)
+ return UNZ_PARAMERROR;
+ s=(unz_s*)file;
+ if (ZSEEK(s->z_filefunc, s->filestream,
+ s->pos_in_central_dir+s->byte_before_the_zipfile,
+ ZLIB_FILEFUNC_SEEK_SET)!=0)
+ err=UNZ_ERRNO;
+
+
+ /* we check the magic */
+ if (err==UNZ_OK){
+ if (unzlocal_getLong(&s->z_filefunc, s->filestream,&uMagic) != UNZ_OK)
+ err=UNZ_ERRNO;
+ else if (uMagic!=0x02014b50)
+ err=UNZ_BADZIPFILE;
+ }
+
+ if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.version) != UNZ_OK)
+ err=UNZ_ERRNO;
+
+ if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.version_needed) != UNZ_OK)
+ err=UNZ_ERRNO;
+
+ if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.flag) != UNZ_OK)
+ err=UNZ_ERRNO;
+
+ if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.compression_method) != UNZ_OK)
+ err=UNZ_ERRNO;
+
+ if (unzlocal_getLong(&s->z_filefunc, s->filestream,&file_info.dosDate) != UNZ_OK)
+ err=UNZ_ERRNO;
+
+ unzlocal_DosDateToTmuDate(file_info.dosDate,&file_info.tmu_date);
+
+ if (unzlocal_getLong(&s->z_filefunc, s->filestream,&file_info.crc) != UNZ_OK)
+ err=UNZ_ERRNO;
+
+ if (unzlocal_getLong(&s->z_filefunc, s->filestream,&file_info.compressed_size) != UNZ_OK)
+ err=UNZ_ERRNO;
+
+ if (unzlocal_getLong(&s->z_filefunc, s->filestream,&file_info.uncompressed_size) != UNZ_OK)
+ err=UNZ_ERRNO;
+
+ if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.size_filename) != UNZ_OK)
+ err=UNZ_ERRNO;
+
+ if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.size_file_extra) != UNZ_OK)
+ err=UNZ_ERRNO;
+
+ if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.size_file_comment) != UNZ_OK)
+ err=UNZ_ERRNO;
+
+ if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.disk_num_start) != UNZ_OK)
+ err=UNZ_ERRNO;
+
+ if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.internal_fa) != UNZ_OK)
+ err=UNZ_ERRNO;
+
+ if (unzlocal_getLong(&s->z_filefunc, s->filestream,&file_info.external_fa) != UNZ_OK)
+ err=UNZ_ERRNO;
+
+ if (unzlocal_getLong(&s->z_filefunc, s->filestream,&file_info_internal.offset_curfile) != UNZ_OK)
+ err=UNZ_ERRNO;
+
+ lSeek+=file_info.size_filename;
+ if ((err==UNZ_OK) && (szFileName!=NULL))
+ {
+ uLong uSizeRead ;
+ if (file_info.size_filename<fileNameBufferSize)
+ {
+ *(szFileName+file_info.size_filename)='\0';
+ uSizeRead = file_info.size_filename;
+ }
+ else
+ uSizeRead = fileNameBufferSize;
+
+ if ((file_info.size_filename>0) && (fileNameBufferSize>0))
+ if (ZREAD(s->z_filefunc, s->filestream,szFileName,uSizeRead)!=uSizeRead)
+ err=UNZ_ERRNO;
+ lSeek -= uSizeRead;
+ }
+
+
+ if ((err==UNZ_OK) && (extraField!=NULL))
+ {
+ uLong uSizeRead ;
+ if (file_info.size_file_extra<extraFieldBufferSize)
+ uSizeRead = file_info.size_file_extra;
+ else
+ uSizeRead = extraFieldBufferSize;
+
+ if (lSeek!=0){
+ if (ZSEEK(s->z_filefunc, s->filestream,lSeek,ZLIB_FILEFUNC_SEEK_CUR)==0)
+ lSeek=0;
+ else
+ err=UNZ_ERRNO;
+ }
+ if ((file_info.size_file_extra>0) && (extraFieldBufferSize>0))
+ if (ZREAD(s->z_filefunc, s->filestream,extraField,uSizeRead)!=uSizeRead)
+ err=UNZ_ERRNO;
+ lSeek += file_info.size_file_extra - uSizeRead;
+ }
+ else
+ lSeek+=file_info.size_file_extra;
+
+
+ if ((err==UNZ_OK) && (szComment!=NULL))
+ {
+ uLong uSizeRead ;
+ if (file_info.size_file_comment<commentBufferSize)
+ {
+ *(szComment+file_info.size_file_comment)='\0';
+ uSizeRead = file_info.size_file_comment;
+ }
+ else
+ uSizeRead = commentBufferSize;
+
+ if (lSeek!=0){
+ if (ZSEEK(s->z_filefunc, s->filestream,lSeek,ZLIB_FILEFUNC_SEEK_CUR)==0)
+ lSeek=0;
+ else
+ err=UNZ_ERRNO;
+ }
+ if ((file_info.size_file_comment>0) && (commentBufferSize>0))
+ if (ZREAD(s->z_filefunc, s->filestream,szComment,uSizeRead)!=uSizeRead)
+ err=UNZ_ERRNO;
+ lSeek+=file_info.size_file_comment - uSizeRead;
+ }
+ else
+ lSeek+=file_info.size_file_comment;
+
+ if ((err==UNZ_OK) && (pfile_info!=NULL))
+ *pfile_info=file_info;
+
+ if ((err==UNZ_OK) && (pfile_info_internal!=NULL))
+ *pfile_info_internal=file_info_internal;
+
+ return err;
+}
+
+int unzGetCurrentFileInfo(unzFile file,
+ unz_file_info *pfile_info,
+ char *szFileName,
+ uLong fileNameBufferSize,
+ void *extraField,
+ uLong extraFieldBufferSize,
+ char *szComment,
+ uLong commentBufferSize)
+{
+ return unzlocal_GetCurrentFileInfoInternal(file, pfile_info, NULL, szFileName, fileNameBufferSize, extraField, extraFieldBufferSize, szComment, commentBufferSize);
+}
+
+/*
+ Set the current file of the zipfile to the next file.
+ return UNZ_OK if there is no problem
+ return UNZ_END_OF_LIST_OF_FILE if the actual file was the latest.
+*/
+int unzGoToNextFile (file)
+ unzFile file;
+{
+ unz_s* s;
+ int err;
+
+ if (file==NULL)
+ return UNZ_PARAMERROR;
+ s=(unz_s*)file;
+ if (!s->current_file_ok)
+ return UNZ_END_OF_LIST_OF_FILE;
+ if (s->gi.number_entry != 0xffff) /* 2^16 files overflow hack */
+ if (s->num_file+1==s->gi.number_entry)
+ return UNZ_END_OF_LIST_OF_FILE;
+
+ s->pos_in_central_dir += SIZECENTRALDIRITEM + s->cur_file_info.size_filename +
+ s->cur_file_info.size_file_extra + s->cur_file_info.size_file_comment ;
+ s->num_file++;
+ err = unzlocal_GetCurrentFileInfoInternal(file,&s->cur_file_info,
+ &s->cur_file_info_internal,
+ NULL,0,NULL,0,NULL,0);
+ s->current_file_ok = (err == UNZ_OK);
+ return err;
+}
+
+/*
+ Set the current file of the zipfile to the first file.
+ return UNZ_OK if there is no problem
+*/
+int unzGoToFirstFile (file)
+ unzFile file;
+{
+ int err=UNZ_OK;
+ unz_s* s;
+ if (file==NULL)
+ return UNZ_PARAMERROR;
+ s=(unz_s*)file;
+ s->pos_in_central_dir=s->offset_central_dir;
+ s->num_file=0;
+ err=unzlocal_GetCurrentFileInfoInternal(file,&s->cur_file_info,
+ &s->cur_file_info_internal,
+ NULL,0,NULL,0,NULL,0);
+ s->current_file_ok = (err == UNZ_OK);
+ return err;
+}
+
+int unzGetGlobalInfo (file,pglobal_info)
+ unzFile file;
+ unz_global_info *pglobal_info;
+{
+ unz_s* s;
+ if (file==NULL)
+ return UNZ_PARAMERROR;
+ s=(unz_s*)file;
+ *pglobal_info=s->gi;
+ return UNZ_OK;
+}
+
+/*
+ Close the file in zip opened with unzipOpenCurrentFile
+ Return UNZ_CRCERROR if all the file was read but the CRC is not good
+*/
+int unzCloseCurrentFile (file)
+ unzFile file;
+{
+ int err=UNZ_OK;
+
+ unz_s* s;
+ file_in_zip_read_info_s* pfile_in_zip_read_info;
+ if (file==NULL)
+ return UNZ_PARAMERROR;
+ s=(unz_s*)file;
+ pfile_in_zip_read_info=s->pfile_in_zip_read;
+
+ if (pfile_in_zip_read_info==NULL)
+ return UNZ_PARAMERROR;
+
+
+ if ((pfile_in_zip_read_info->rest_read_uncompressed == 0) &&
+ (!pfile_in_zip_read_info->raw))
+ {
+ if (pfile_in_zip_read_info->crc32 != pfile_in_zip_read_info->crc32_wait)
+ err=UNZ_CRCERROR;
+ }
+
+
+ TRYFREE(pfile_in_zip_read_info->read_buffer);
+ pfile_in_zip_read_info->read_buffer = NULL;
+ if (pfile_in_zip_read_info->stream_initialised)
+ inflateEnd(&pfile_in_zip_read_info->stream);
+
+ pfile_in_zip_read_info->stream_initialised = 0;
+ TRYFREE(pfile_in_zip_read_info);
+
+ s->pfile_in_zip_read=NULL;
+
+ return err;
+}
+
+
+/*
+ Open a Zip file. path contain the full pathname (by example,
+ on a Windows NT computer "c:\\test\\zlib114.zip" or on an Unix computer
+ "zlib/zlib114.zip".
+ If the zipfile cannot be opened (file doesn't exist or in not valid), the
+ return value is NULL.
+ Else, the return value is a unzFile Handle, usable with other function
+ of this unzip package.
+*/
+extern unzFile ZEXPORT unzOpen2 (path, pzlib_filefunc_def)
+ const char *path;
+ zlib_filefunc_def* pzlib_filefunc_def;
+{
+ unz_s us;
+ unz_s *s;
+ uLong central_pos,uL;
+
+ uLong number_disk; /* number of the current dist, used for
+ spaning ZIP, unsupported, always 0*/
+ uLong number_disk_with_CD; /* number the the disk with central dir, used
+ for spaning ZIP, unsupported, always 0*/
+ uLong number_entry_CD; /* total number of entries in
+ the central dir
+ (same than number_entry on nospan) */
+
+ int err=UNZ_OK;
+
+ if (pzlib_filefunc_def==NULL)
+ fill_fopen_filefunc(&us.z_filefunc);
+ else
+ us.z_filefunc = *pzlib_filefunc_def;
+
+ us.filestream= (*(us.z_filefunc.zopen_file))(us.z_filefunc.opaque,
+ path,
+ ZLIB_FILEFUNC_MODE_READ |
+ ZLIB_FILEFUNC_MODE_EXISTING);
+ if (us.filestream==NULL)
+ return NULL;
+
+ central_pos = unzlocal_SearchCentralDir(&us.z_filefunc,us.filestream);
+ if (central_pos==0)
+ err=UNZ_ERRNO;
+
+ if (ZSEEK(us.z_filefunc, us.filestream,
+ central_pos,ZLIB_FILEFUNC_SEEK_SET)!=0)
+ err=UNZ_ERRNO;
+
+ /* the signature, already checked */
+ if (unzlocal_getLong(&us.z_filefunc, us.filestream,&uL)!=UNZ_OK)
+ err=UNZ_ERRNO;
+
+ /* number of this disk */
+ if (unzlocal_getShort(&us.z_filefunc, us.filestream,&number_disk)!=UNZ_OK)
+ err=UNZ_ERRNO;
+
+ /* number of the disk with the start of the central directory */
+ if (unzlocal_getShort(&us.z_filefunc, us.filestream,&number_disk_with_CD)!=UNZ_OK)
+ err=UNZ_ERRNO;
+
+ /* total number of entries in the central dir on this disk */
+ if (unzlocal_getShort(&us.z_filefunc, us.filestream,&us.gi.number_entry)!=UNZ_OK)
+ err=UNZ_ERRNO;
+
+ /* total number of entries in the central dir */
+ if (unzlocal_getShort(&us.z_filefunc, us.filestream,&number_entry_CD)!=UNZ_OK)
+ err=UNZ_ERRNO;
+
+ if ((number_entry_CD!=us.gi.number_entry) ||
+ (number_disk_with_CD!=0) ||
+ (number_disk!=0))
+ err=UNZ_BADZIPFILE;
+
+ /* size of the central directory */
+ if (unzlocal_getLong(&us.z_filefunc, us.filestream,&us.size_central_dir)!=UNZ_OK)
+ err=UNZ_ERRNO;
+
+ /* offset of start of central directory with respect to the
+ starting disk number */
+ if (unzlocal_getLong(&us.z_filefunc, us.filestream,&us.offset_central_dir)!=UNZ_OK)
+ err=UNZ_ERRNO;
+
+ /* zipfile comment length */
+ if (unzlocal_getShort(&us.z_filefunc, us.filestream,&us.gi.size_comment)!=UNZ_OK)
+ err=UNZ_ERRNO;
+
+ if ((central_pos<us.offset_central_dir+us.size_central_dir) &&
+ (err==UNZ_OK))
+ err=UNZ_BADZIPFILE;
+
+ if (err!=UNZ_OK)
+ {
+ ZCLOSE(us.z_filefunc, us.filestream);
+ return NULL;
+ }
+
+ us.byte_before_the_zipfile = central_pos -
+ (us.offset_central_dir+us.size_central_dir);
+ us.central_pos = central_pos;
+ us.pfile_in_zip_read = NULL;
+ us.encrypted = 0;
+
+
+ s=(unz_s*)ALLOC(sizeof(unz_s));
+ *s=us;
+ unzGoToFirstFile((unzFile)s);
+ return (unzFile)s;
+}
+
+
+/*
+ Read bytes from the current file.
+ buf contain buffer where data must be copied
+ len the size of buf.
+
+ return the number of byte copied if somes bytes are copied
+ return 0 if the end of file was reached
+ return <0 with error code if there is an error
+ (UNZ_ERRNO for IO error, or zLib error for uncompress error)
+*/
+int unzReadCurrentFile (file, buf, len)
+ unzFile file;
+ voidp buf;
+ unsigned len;
+{
+ int err=UNZ_OK;
+ uInt iRead = 0;
+ unz_s* s;
+ file_in_zip_read_info_s* pfile_in_zip_read_info;
+ if (file==NULL)
+ return UNZ_PARAMERROR;
+ s=(unz_s*)file;
+ pfile_in_zip_read_info=s->pfile_in_zip_read;
+
+ if (pfile_in_zip_read_info==NULL)
+ return UNZ_PARAMERROR;
+
+
+ if ((pfile_in_zip_read_info->read_buffer == NULL))
+ return UNZ_END_OF_LIST_OF_FILE;
+ if (len==0)
+ return 0;
+
+ pfile_in_zip_read_info->stream.next_out = (Bytef*)buf;
+
+ pfile_in_zip_read_info->stream.avail_out = (uInt)len;
+
+ if ((len>pfile_in_zip_read_info->rest_read_uncompressed) &&
+ (!(pfile_in_zip_read_info->raw)))
+ pfile_in_zip_read_info->stream.avail_out =
+ (uInt)pfile_in_zip_read_info->rest_read_uncompressed;
+
+ if ((len>pfile_in_zip_read_info->rest_read_compressed+
+ pfile_in_zip_read_info->stream.avail_in) &&
+ (pfile_in_zip_read_info->raw))
+ pfile_in_zip_read_info->stream.avail_out =
+ (uInt)pfile_in_zip_read_info->rest_read_compressed+
+ pfile_in_zip_read_info->stream.avail_in;
+
+ while (pfile_in_zip_read_info->stream.avail_out>0)
+ {
+ if ((pfile_in_zip_read_info->stream.avail_in==0) &&
+ (pfile_in_zip_read_info->rest_read_compressed>0))
+ {
+ uInt uReadThis = UNZ_BUFSIZE;
+ if (pfile_in_zip_read_info->rest_read_compressed<uReadThis)
+ uReadThis = (uInt)pfile_in_zip_read_info->rest_read_compressed;
+ if (uReadThis == 0)
+ return UNZ_EOF;
+ if (ZSEEK(pfile_in_zip_read_info->z_filefunc,
+ pfile_in_zip_read_info->filestream,
+ pfile_in_zip_read_info->pos_in_zipfile +
+ pfile_in_zip_read_info->byte_before_the_zipfile,
+ ZLIB_FILEFUNC_SEEK_SET)!=0)
+ return UNZ_ERRNO;
+ if (ZREAD(pfile_in_zip_read_info->z_filefunc,
+ pfile_in_zip_read_info->filestream,
+ pfile_in_zip_read_info->read_buffer,
+ uReadThis)!=uReadThis)
+ return UNZ_ERRNO;
+
+ pfile_in_zip_read_info->pos_in_zipfile += uReadThis;
+
+ pfile_in_zip_read_info->rest_read_compressed-=uReadThis;
+
+ pfile_in_zip_read_info->stream.next_in =
+ (Bytef*)pfile_in_zip_read_info->read_buffer;
+ pfile_in_zip_read_info->stream.avail_in = (uInt)uReadThis;
+ }
+
+ if ((pfile_in_zip_read_info->compression_method==0) || (pfile_in_zip_read_info->raw))
+ {
+ uInt uDoCopy,i ;
+
+ if ((pfile_in_zip_read_info->stream.avail_in == 0) &&
+ (pfile_in_zip_read_info->rest_read_compressed == 0))
+ return (iRead==0) ? UNZ_EOF : iRead;
+
+ if (pfile_in_zip_read_info->stream.avail_out <
+ pfile_in_zip_read_info->stream.avail_in)
+ uDoCopy = pfile_in_zip_read_info->stream.avail_out ;
+ else
+ uDoCopy = pfile_in_zip_read_info->stream.avail_in ;
+
+ for (i=0;i<uDoCopy;i++)
+ *(pfile_in_zip_read_info->stream.next_out+i) =
+ *(pfile_in_zip_read_info->stream.next_in+i);
+
+ pfile_in_zip_read_info->crc32 = crc32(pfile_in_zip_read_info->crc32,
+ pfile_in_zip_read_info->stream.next_out,
+ uDoCopy);
+ pfile_in_zip_read_info->rest_read_uncompressed-=uDoCopy;
+ pfile_in_zip_read_info->stream.avail_in -= uDoCopy;
+ pfile_in_zip_read_info->stream.avail_out -= uDoCopy;
+ pfile_in_zip_read_info->stream.next_out += uDoCopy;
+ pfile_in_zip_read_info->stream.next_in += uDoCopy;
+ pfile_in_zip_read_info->stream.total_out += uDoCopy;
+ iRead += uDoCopy;
+ }
+ else
+ {
+ uLong uTotalOutBefore,uTotalOutAfter;
+ const Bytef *bufBefore;
+ uLong uOutThis;
+ int flush=Z_SYNC_FLUSH;
+
+ uTotalOutBefore = pfile_in_zip_read_info->stream.total_out;
+ bufBefore = pfile_in_zip_read_info->stream.next_out;
+
+ /*
+ if ((pfile_in_zip_read_info->rest_read_uncompressed ==
+ pfile_in_zip_read_info->stream.avail_out) &&
+ (pfile_in_zip_read_info->rest_read_compressed == 0))
+ flush = Z_FINISH;
+ */
+ err=inflate(&pfile_in_zip_read_info->stream,flush);
+
+ if ((err>=0) && (pfile_in_zip_read_info->stream.msg!=NULL))
+ err = Z_DATA_ERROR;
+
+ uTotalOutAfter = pfile_in_zip_read_info->stream.total_out;
+ uOutThis = uTotalOutAfter-uTotalOutBefore;
+
+ pfile_in_zip_read_info->crc32 =
+ crc32(pfile_in_zip_read_info->crc32,bufBefore,
+ (uInt)(uOutThis));
+
+ pfile_in_zip_read_info->rest_read_uncompressed -=
+ uOutThis;
+
+ iRead += (uInt)(uTotalOutAfter - uTotalOutBefore);
+
+ if (err==Z_STREAM_END)
+ return (iRead==0) ? UNZ_EOF : iRead;
+ if (err!=Z_OK)
+ break;
+ }
+ }
+
+ if (err==Z_OK)
+ return iRead;
+ return err;
+}
+
+/*
+ Read the local header of the current zipfile
+ Check the coherency of the local header and info in the end of central
+ directory about this file
+ store in *piSizeVar the size of extra info in local header
+ (filename and size of extra field data)
+*/
+int unzlocal_CheckCurrentFileCoherencyHeader (s,piSizeVar,
+ poffset_local_extrafield,
+ psize_local_extrafield)
+ unz_s* s;
+ uInt* piSizeVar;
+ uLong *poffset_local_extrafield;
+ uInt *psize_local_extrafield;
+{
+ uLong uMagic,uData,uFlags;
+ uLong size_filename;
+ uLong size_extra_field;
+ int err=UNZ_OK;
+
+ *piSizeVar = 0;
+ *poffset_local_extrafield = 0;
+ *psize_local_extrafield = 0;
+
+ if (ZSEEK(s->z_filefunc, s->filestream,s->cur_file_info_internal.offset_curfile +
+ s->byte_before_the_zipfile,ZLIB_FILEFUNC_SEEK_SET)!=0)
+ return UNZ_ERRNO;
+
+
+ if (err==UNZ_OK){
+ if (unzlocal_getLong(&s->z_filefunc, s->filestream,&uMagic) != UNZ_OK)
+ err=UNZ_ERRNO;
+ else if (uMagic!=0x04034b50)
+ err=UNZ_BADZIPFILE;
+ }
+
+ if (unzlocal_getShort(&s->z_filefunc, s->filestream,&uData) != UNZ_OK)
+ err=UNZ_ERRNO;
+/*
+ else if ((err==UNZ_OK) && (uData!=s->cur_file_info.wVersion))
+ err=UNZ_BADZIPFILE;
+*/
+ if (unzlocal_getShort(&s->z_filefunc, s->filestream,&uFlags) != UNZ_OK)
+ err=UNZ_ERRNO;
+
+ if (unzlocal_getShort(&s->z_filefunc, s->filestream,&uData) != UNZ_OK)
+ err=UNZ_ERRNO;
+ else if ((err==UNZ_OK) && (uData!=s->cur_file_info.compression_method))
+ err=UNZ_BADZIPFILE;
+
+ if ((err==UNZ_OK) && (s->cur_file_info.compression_method!=0) &&
+ (s->cur_file_info.compression_method!=Z_DEFLATED))
+ err=UNZ_BADZIPFILE;
+
+ if (unzlocal_getLong(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) /* date/time */
+ err=UNZ_ERRNO;
+
+ if (unzlocal_getLong(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) /* crc */
+ err=UNZ_ERRNO;
+ else if ((err==UNZ_OK) && (uData!=s->cur_file_info.crc) &&
+ ((uFlags & 8)==0))
+ err=UNZ_BADZIPFILE;
+
+ if (unzlocal_getLong(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) /* size compr */
+ err=UNZ_ERRNO;
+ else if ((err==UNZ_OK) && (uData!=s->cur_file_info.compressed_size) &&
+ ((uFlags & 8)==0))
+ err=UNZ_BADZIPFILE;
+
+ if (unzlocal_getLong(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) /* size uncompr */
+ err=UNZ_ERRNO;
+ else if ((err==UNZ_OK) && (uData!=s->cur_file_info.uncompressed_size) &&
+ ((uFlags & 8)==0))
+ err=UNZ_BADZIPFILE;
+
+
+ if (unzlocal_getShort(&s->z_filefunc, s->filestream,&size_filename) != UNZ_OK)
+ err=UNZ_ERRNO;
+ else if ((err==UNZ_OK) && (size_filename!=s->cur_file_info.size_filename))
+ err=UNZ_BADZIPFILE;
+
+ *piSizeVar += (uInt)size_filename;
+
+ if (unzlocal_getShort(&s->z_filefunc, s->filestream,&size_extra_field) != UNZ_OK)
+ err=UNZ_ERRNO;
+ *poffset_local_extrafield= s->cur_file_info_internal.offset_curfile +
+ SIZEZIPLOCALHEADER + size_filename;
+ *psize_local_extrafield = (uInt)size_extra_field;
+
+ *piSizeVar += (uInt)size_extra_field;
+
+ return err;
+}
+
+/*
+ Open for reading data the current file in the zipfile.
+ If there is no error and the file is opened, the return value is UNZ_OK.
+*/
+int unzOpenCurrentFile3 (file, method, level, raw, password)
+ unzFile file;
+ int* method;
+ int* level;
+ int raw;
+ const char* password;
+{
+ int err=UNZ_OK;
+ uInt iSizeVar;
+ unz_s* s;
+ file_in_zip_read_info_s* pfile_in_zip_read_info;
+ uLong offset_local_extrafield; /* offset of the local extra field */
+ uInt size_local_extrafield; /* size of the local extra field */
+
+ if (password != NULL)
+ return UNZ_PARAMERROR;
+
+ if (file==NULL)
+ return UNZ_PARAMERROR;
+ s=(unz_s*)file;
+ if (!s->current_file_ok)
+ return UNZ_PARAMERROR;
+
+ if (s->pfile_in_zip_read != NULL)
+ unzCloseCurrentFile(file);
+
+ if (unzlocal_CheckCurrentFileCoherencyHeader(s,&iSizeVar,
+ &offset_local_extrafield,&size_local_extrafield)!=UNZ_OK)
+ return UNZ_BADZIPFILE;
+
+ pfile_in_zip_read_info = (file_in_zip_read_info_s*)
+ ALLOC(sizeof(file_in_zip_read_info_s));
+ if (pfile_in_zip_read_info==NULL)
+ return UNZ_INTERNALERROR;
+
+ pfile_in_zip_read_info->read_buffer=(char*)ALLOC(UNZ_BUFSIZE);
+ pfile_in_zip_read_info->offset_local_extrafield = offset_local_extrafield;
+ pfile_in_zip_read_info->size_local_extrafield = size_local_extrafield;
+ pfile_in_zip_read_info->pos_local_extrafield=0;
+ pfile_in_zip_read_info->raw=raw;
+
+ if (pfile_in_zip_read_info->read_buffer==NULL)
+ {
+ TRYFREE(pfile_in_zip_read_info);
+ return UNZ_INTERNALERROR;
+ }
+
+ pfile_in_zip_read_info->stream_initialised=0;
+
+ if (method!=NULL)
+ *method = (int)s->cur_file_info.compression_method;
+
+ if (level!=NULL)
+ {
+ *level = 6;
+ switch (s->cur_file_info.flag & 0x06)
+ {
+ case 6 : *level = 1; break;
+ case 4 : *level = 2; break;
+ case 2 : *level = 9; break;
+ }
+ }
+
+ if ((s->cur_file_info.compression_method!=0) &&
+ (s->cur_file_info.compression_method!=Z_DEFLATED))
+ err=UNZ_BADZIPFILE;
+
+ pfile_in_zip_read_info->crc32_wait=s->cur_file_info.crc;
+ pfile_in_zip_read_info->crc32=0;
+ pfile_in_zip_read_info->compression_method =
+ s->cur_file_info.compression_method;
+ pfile_in_zip_read_info->filestream=s->filestream;
+ pfile_in_zip_read_info->z_filefunc=s->z_filefunc;
+ pfile_in_zip_read_info->byte_before_the_zipfile=s->byte_before_the_zipfile;
+
+ pfile_in_zip_read_info->stream.total_out = 0;
+
+ if ((s->cur_file_info.compression_method==Z_DEFLATED) &&
+ (!raw))
+ {
+ pfile_in_zip_read_info->stream.zalloc = (alloc_func)0;
+ pfile_in_zip_read_info->stream.zfree = (free_func)0;
+ pfile_in_zip_read_info->stream.opaque = (voidpf)0;
+ pfile_in_zip_read_info->stream.next_in = (voidpf)0;
+ pfile_in_zip_read_info->stream.avail_in = 0;
+
+ err=inflateInit2(&pfile_in_zip_read_info->stream, -MAX_WBITS);
+ if (err == Z_OK)
+ pfile_in_zip_read_info->stream_initialised=1;
+ else
+ {
+ TRYFREE(pfile_in_zip_read_info);
+ return err;
+ }
+ /* windowBits is passed < 0 to tell that there is no zlib header.
+ * Note that in this case inflate *requires* an extra "dummy" byte
+ * after the compressed stream in order to complete decompression and
+ * return Z_STREAM_END.
+ * In unzip, i don't wait absolutely Z_STREAM_END because I known the
+ * size of both compressed and uncompressed data
+ */
+ }
+ pfile_in_zip_read_info->rest_read_compressed =
+ s->cur_file_info.compressed_size ;
+ pfile_in_zip_read_info->rest_read_uncompressed =
+ s->cur_file_info.uncompressed_size ;
+
+
+ pfile_in_zip_read_info->pos_in_zipfile =
+ s->cur_file_info_internal.offset_curfile + SIZEZIPLOCALHEADER +
+ iSizeVar;
+
+ pfile_in_zip_read_info->stream.avail_in = (uInt)0;
+
+ s->pfile_in_zip_read = pfile_in_zip_read_info;
+
+ return UNZ_OK;
+}
+
+/*
+ Close a ZipFile opened with unzipOpen.
+ If there is files inside the .Zip opened with unzipOpenCurrentFile (see later),
+ these files MUST be closed with unzipCloseCurrentFile before call unzipClose.
+ return UNZ_OK if there is no problem. */
+extern int ZEXPORT unzClose (file)
+ unzFile file;
+{
+ unz_s* s;
+ if (file==NULL)
+ return UNZ_PARAMERROR;
+ s=(unz_s*)file;
+
+ if (s->pfile_in_zip_read!=NULL)
+ unzCloseCurrentFile(file);
+
+ ZCLOSE(s->z_filefunc, s->filestream);
+ TRYFREE(s);
+ return UNZ_OK;
+}
+
+#ifndef _WIN32_WCE
+
+/* mymkdir and change_file_date are not 100 % portable
+ As I don't know well Unix, I wait feedback for the unix portion */
+
+int mymkdir(dirname)
+ const char* dirname;
+{
+ int ret=0;
+#if defined(WIN32) || defined(_WIN32_WCE)
+ return mkdir(dirname);
+#else
+ return mkdir (dirname, 700);
+#endif
+ return ret;
+}
+
+int makedir (newdir)
+ char *newdir;
+{
+ char *buffer ;
+ char *p;
+ int len = (int)strlen(newdir);
+
+ if (len <= 0)
+ return 0;
+
+ buffer = (char*)gf_malloc(len+1);
+ strcpy(buffer,newdir);
+
+ if (buffer[len-1] == '/') {
+ buffer[len-1] = '\0';
+ }
+ if (mymkdir(buffer) == 0)
+ {
+ gf_free(buffer);
+ return 1;
+ }
+
+ p = buffer+1;
+ while (1)
+ {
+ char hold;
+
+ while(*p && *p != '\\' && *p != '/')
+ p++;
+ hold = *p;
+ *p = 0;
+ if ((mymkdir(buffer) == -1) && (errno == ENOENT))
+ {
+ printf("couldn't create directory %s\n",buffer);
+ gf_free(buffer);
+ return 0;
+ }
+ if (hold == 0)
+ break;
+ *p++ = hold;
+ }
+ gf_free(buffer);
+ return 1;
+}
+#else
+int makedir (newdir)
+{
+ return 0;
+}
+#endif
+
+
+int do_extract_currentfile(uf)
+ unzFile uf;
+{
+ char filename_inzip[256];
+ char* filename_withoutpath;
+ char* p;
+ int err=UNZ_OK;
+ FILE *fout=NULL;
+ void* buf;
+ uInt size_buf;
+
+ unz_file_info file_info;
+ err = unzlocal_GetCurrentFileInfoInternal(uf,&file_info,NULL,filename_inzip,sizeof(filename_inzip),NULL,0,NULL,0);
+
+ if (err!=UNZ_OK)
+ {
+ printf("error %d with zipfile in unzGetCurrentFileInfo\n",err);
+ return err;
+ }
+
+ size_buf = WRITEBUFFERSIZE;
+ buf = (void*)gf_malloc(size_buf);
+ if (buf==NULL)
+ {
+ printf("Error allocating memory\n");
+ return UNZ_INTERNALERROR;
+ }
+
+ p = filename_withoutpath = filename_inzip;
+ while ((*p) != '\0')
+ {
+ if (((*p)=='/') || ((*p)=='\\'))
+ filename_withoutpath = p+1;
+ p++;
+ }
+
+ if ((*filename_withoutpath)=='\0')
+ {
+#ifndef _WIN32_WCE
+ printf("creating directory: %s\n",filename_inzip);
+ mymkdir(filename_inzip);
+#endif
+ }
+ else
+ {
+ const char* write_filename;
+ int skip=0;
+
+ write_filename = filename_inzip;
+
+ err = unzOpenCurrentFile3(uf, NULL, NULL, 0, NULL/*password*/);
+ if (err!=UNZ_OK)
+ {
+ printf("error %d with zipfile in unzOpenCurrentFilePassword\n",err);
+ }
+
+ if ((skip==0) && (err==UNZ_OK))
+ {
+ fout=fopen(write_filename,"wb");
+
+ /* some zipfile don't contain directory alone before file */
+ if ((fout==NULL) && (filename_withoutpath!=(char*)filename_inzip))
+ {
+ char c=*(filename_withoutpath-1);
+ *(filename_withoutpath-1)='\0';
+ makedir(write_filename);
+ *(filename_withoutpath-1)=c;
+ fout=fopen(write_filename,"wb");
+ }
+
+ if (fout==NULL)
+ {
+ printf("error opening %s\n",write_filename);
+ }
+ }
+
+ if (fout!=NULL)
+ {
+ printf(" extracting: %s\n",write_filename);
+
+ do
+ {
+ err = unzReadCurrentFile(uf,buf,size_buf);
+ if (err<0)
+ {
+ printf("error %d with zipfile in unzReadCurrentFile\n",err);
+ break;
+ }
+ if (err>0)
+ if (gf_fwrite(buf,err,1,fout)!=1)
+ {
+ printf("error in writing extracted file\n");
+ err=UNZ_ERRNO;
+ break;
+ }
+ }
+ while (err>0);
+ if (fout)
+ fclose(fout);
+ }
+
+ if (err==UNZ_OK)
+ {
+ err = unzCloseCurrentFile (uf);
+ if (err!=UNZ_OK)
+ {
+ printf("error %d with zipfile in unzCloseCurrentFile\n",err);
+ }
+ }
+ else
+ unzCloseCurrentFile(uf); /* don't lose the error */
+ }
+
+ gf_free(buf);
+ return err;
+}
+
+
+int gf_unzip_archive(const char *zipfilename, const char *dirname)
+{
+ uLong i;
+ unz_global_info gi;
+ int err;
+
+ unzFile uf=NULL;
+
+ uf = unzOpen2(zipfilename, NULL);
+ if (uf==NULL)
+ {
+ printf("Cannot open %s\n", zipfilename);
+ return 1;
+ }
+#ifndef _WIN32_WCE
+ if (chdir(dirname))
+ {
+ printf("Error changing into %s, aborting\n", dirname);
+ exit(-1);
+ }
+#endif
+
+ err = unzGetGlobalInfo (uf,&gi);
+ if (err!=UNZ_OK)
+ printf("error %d with zipfile in unzGetGlobalInfo \n",err);
+
+ for (i=0;i<gi.number_entry;i++)
+ {
+ if (do_extract_currentfile(uf) != UNZ_OK)
+ break;
+
+ if ((i+1)<gi.number_entry)
+ {
+ err = unzGoToNextFile(uf);
+ if (err!=UNZ_OK)
+ {
+ printf("error %d with zipfile in unzGoToNextFile\n",err);
+ break;
+ }
+ }
+ }
+ unzClose(uf);
+
+ return 0;
+}
+
+int gf_unzip_probe(const char *zipfilename)
+{
+ int ret = 0;
+ FILE *f = fopen(zipfilename, "r");
+ if (!f) return 0;
+ if (fgetc(f)=='P')
+ if (fgetc(f)=='K')
+ if (fgetc(f)==3)
+ if (fgetc(f)==4)
+ ret = 1;
+ fclose(f);
+ return ret;
+}
--- /dev/null
+/* unzip.h -- IO for uncompress .zip files using zlib
+ Version 1.01e, February 12th, 2005
+
+ Copyright (C) 1998-2005 Gilles Vollant
+
+ This unzip package allow extract file from .ZIP file, compatible with PKZip 2.04g
+ WinZip, InfoZip tools and compatible.
+
+ Multi volume ZipFile (span) are not supported.
+ Encryption compatible with pkzip 2.04g only supported
+ Old compressions used by old PKZip 1.x are not supported
+
+
+ I WAIT FEEDBACK at mail info@winimage.com
+ Visit also http://www.winimage.com/zLibDll/unzip.htm for evolution
+
+ Condition of use and distribution are the same than zlib :
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+
+
+*/
+
+/* for more info about .ZIP format, see
+ http://www.info-zip.org/pub/infozip/doc/appnote-981119-iz.zip
+ http://www.info-zip.org/pub/infozip/doc/
+ PkWare has also a specification at :
+ ftp://ftp.pkware.com/probdesc.zip
+*/
+
+#ifndef _unz_H
+#define _unz_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+# include <zlib.h>
+
+#ifndef OF
+#define OF(x) x
+#endif
+
+#define ZCALLBACK
+
+#define ZLIB_FILEFUNC_SEEK_CUR (1)
+#define ZLIB_FILEFUNC_SEEK_END (2)
+#define ZLIB_FILEFUNC_SEEK_SET (0)
+
+#define ZLIB_FILEFUNC_MODE_READ (1)
+#define ZLIB_FILEFUNC_MODE_WRITE (2)
+#define ZLIB_FILEFUNC_MODE_READWRITEFILTER (3)
+
+#define ZLIB_FILEFUNC_MODE_EXISTING (4)
+#define ZLIB_FILEFUNC_MODE_CREATE (8)
+
+typedef voidpf (ZCALLBACK *open_file_func) OF((voidpf opaque, const char* filename, int mode));
+typedef uLong (ZCALLBACK *read_file_func) OF((voidpf opaque, voidpf stream, void* buf, uLong size));
+typedef uLong (ZCALLBACK *write_file_func) OF((voidpf opaque, voidpf stream, const void* buf, uLong size));
+typedef long (ZCALLBACK *tell_file_func) OF((voidpf opaque, voidpf stream));
+typedef long (ZCALLBACK *seek_file_func) OF((voidpf opaque, voidpf stream, uLong offset, int origin));
+typedef int (ZCALLBACK *close_file_func) OF((voidpf opaque, voidpf stream));
+typedef int (ZCALLBACK *testerror_file_func) OF((voidpf opaque, voidpf stream));
+
+typedef struct zlib_filefunc_def_s
+{
+ open_file_func zopen_file;
+ read_file_func zread_file;
+ write_file_func zwrite_file;
+ tell_file_func ztell_file;
+ seek_file_func zseek_file;
+ close_file_func zclose_file;
+ testerror_file_func zerror_file;
+ voidpf opaque;
+} zlib_filefunc_def;
+
+
+
+void fill_fopen_filefunc OF((zlib_filefunc_def* pzlib_filefunc_def));
+
+#define ZREAD(filefunc,filestream,buf,size) ((*((filefunc).zread_file))((filefunc).opaque,filestream,buf,size))
+#define ZWRITE(filefunc,filestream,buf,size) ((*((filefunc).zwrite_file))((filefunc).opaque,filestream,buf,size))
+#define ZTELL(filefunc,filestream) ((*((filefunc).ztell_file))((filefunc).opaque,filestream))
+#define ZSEEK(filefunc,filestream,pos,mode) ((*((filefunc).zseek_file))((filefunc).opaque,filestream,pos,mode))
+#define ZCLOSE(filefunc,filestream) ((*((filefunc).zclose_file))((filefunc).opaque,filestream))
+#define ZERROR(filefunc,filestream) ((*((filefunc).zerror_file))((filefunc).opaque,filestream))
+
+#if defined(STRICTUNZIP) || defined(STRICTZIPUNZIP)
+/* like the STRICT of WIN32, we define a pointer that cannot be converted
+ from (void*) without cast */
+typedef struct TagunzFile__ { int unused; } unzFile__;
+typedef unzFile__ *unzFile;
+#else
+typedef voidp unzFile;
+#endif
+
+
+#ifndef UNZ_BUFSIZE
+#define UNZ_BUFSIZE (16384)
+#endif
+
+#ifndef UNZ_MAXFILENAMEINZIP
+#define UNZ_MAXFILENAMEINZIP (256)
+#endif
+
+#ifndef ALLOC
+# define ALLOC(size) (gf_malloc(size))
+#endif
+#ifndef TRYFREE
+# define TRYFREE(p) {if (p) gf_free(p);}
+#endif
+
+#define SIZECENTRALDIRITEM (0x2e)
+#define SIZEZIPLOCALHEADER (0x1e)
+
+#ifndef BUFREADCOMMENT
+#define BUFREADCOMMENT (0x400)
+#endif
+
+#define WRITEBUFFERSIZE (8192)
+
+
+
+
+#define UNZ_OK (0)
+#define UNZ_END_OF_LIST_OF_FILE (-100)
+#define UNZ_ERRNO (Z_ERRNO)
+#define UNZ_EOF (0)
+#define UNZ_PARAMERROR (-102)
+#define UNZ_BADZIPFILE (-103)
+#define UNZ_INTERNALERROR (-104)
+#define UNZ_CRCERROR (-105)
+
+/* tm_unz contain date/time info */
+typedef struct tm_unz_s
+{
+ uInt tm_sec; /* seconds after the minute - [0,59] */
+ uInt tm_min; /* minutes after the hour - [0,59] */
+ uInt tm_hour; /* hours since midnight - [0,23] */
+ uInt tm_mday; /* day of the month - [1,31] */
+ uInt tm_mon; /* months since January - [0,11] */
+ uInt tm_year; /* years - [1980..2044] */
+} tm_unz;
+
+/* unz_global_info structure contain global data about the ZIPfile
+ These data comes from the end of central dir */
+typedef struct unz_global_info_s
+{
+ uLong number_entry; /* total number of entries in
+ the central dir on this disk */
+ uLong size_comment; /* size of the global comment of the zipfile */
+} unz_global_info;
+
+
+/* unz_file_info contain information about a file in the zipfile */
+typedef struct unz_file_info_s
+{
+ uLong version; /* version made by 2 bytes */
+ uLong version_needed; /* version needed to extract 2 bytes */
+ uLong flag; /* general purpose bit flag 2 bytes */
+ uLong compression_method; /* compression method 2 bytes */
+ uLong dosDate; /* last mod file date in Dos fmt 4 bytes */
+ uLong crc; /* crc-32 4 bytes */
+ uLong compressed_size; /* compressed size 4 bytes */
+ uLong uncompressed_size; /* uncompressed size 4 bytes */
+ uLong size_filename; /* filename length 2 bytes */
+ uLong size_file_extra; /* extra field length 2 bytes */
+ uLong size_file_comment; /* file comment length 2 bytes */
+
+ uLong disk_num_start; /* disk number start 2 bytes */
+ uLong internal_fa; /* internal file attributes 2 bytes */
+ uLong external_fa; /* external file attributes 4 bytes */
+
+ tm_unz tmu_date;
+} unz_file_info;
+
+
+
+/* unz_file_info_interntal contain internal info about a file in zipfile*/
+typedef struct unz_file_info_internal_s
+{
+ uLong offset_curfile;/* relative offset of local header 4 bytes */
+} unz_file_info_internal;
+
+
+/* file_in_zip_read_info_s contain internal information about a file in zipfile,
+ when reading and decompress it */
+typedef struct
+{
+ char *read_buffer; /* internal buffer for compressed data */
+ z_stream stream; /* zLib stream structure for inflate */
+
+ uLong pos_in_zipfile; /* position in byte on the zipfile, for gf_f64_seek*/
+ uLong stream_initialised; /* flag set if stream structure is initialised*/
+
+ uLong offset_local_extrafield;/* offset of the local extra field */
+ uInt size_local_extrafield;/* size of the local extra field */
+ uLong pos_local_extrafield; /* position in the local extra field in read*/
+
+ uLong crc32; /* crc32 of all data uncompressed */
+ uLong crc32_wait; /* crc32 we must obtain after decompress all */
+ uLong rest_read_compressed; /* number of byte to be decompressed */
+ uLong rest_read_uncompressed;/*number of byte to be obtained after decomp*/
+ zlib_filefunc_def z_filefunc;
+ voidpf filestream; /* io structore of the zipfile */
+ uLong compression_method; /* compression method (0==store) */
+ uLong byte_before_the_zipfile;/* byte before the zipfile, (>0 for sfx)*/
+ int raw;
+} file_in_zip_read_info_s;
+
+
+/* unz_s contain internal information about the zipfile
+*/
+typedef struct
+{
+ zlib_filefunc_def z_filefunc;
+ voidpf filestream; /* io structore of the zipfile */
+ unz_global_info gi; /* public global information */
+ uLong byte_before_the_zipfile;/* byte before the zipfile, (>0 for sfx)*/
+ uLong num_file; /* number of the current file in the zipfile*/
+ uLong pos_in_central_dir; /* pos of the current file in the central dir*/
+ uLong current_file_ok; /* flag about the usability of the current file*/
+ uLong central_pos; /* position of the beginning of the central dir*/
+
+ uLong size_central_dir; /* size of the central directory */
+ uLong offset_central_dir; /* offset of start of central directory with
+ respect to the starting disk number */
+
+ unz_file_info cur_file_info; /* public info about the current file in zip*/
+ unz_file_info_internal cur_file_info_internal; /* private info about it*/
+ file_in_zip_read_info_s* pfile_in_zip_read; /* structure about the current
+ file if we are decompressing it */
+ int encrypted;
+# ifndef NOUNCRYPT
+ unsigned long keys[3]; /* keys defining the pseudo-random sequence */
+ const unsigned long* pcrc_32_tab;
+# endif
+} unz_s;
+
+
+
+extern int ZEXPORT unzStringFileNameCompare OF ((const char* fileName1,
+ const char* fileName2,
+ int iCaseSensitivity));
+/*
+ Compare two filename (fileName1,fileName2).
+ If iCaseSenisivity = 1, comparision is case sensitivity (like strcmp)
+ If iCaseSenisivity = 2, comparision is not case sensitivity (like strcmpi
+ or strcasecmp)
+ If iCaseSenisivity = 0, case sensitivity is defaut of your operating system
+ (like 1 on Unix, 2 on Windows)
+*/
+
+
+extern unzFile ZEXPORT unzOpen OF((const char *path));
+/*
+ Open a Zip file. path contain the full pathname (by example,
+ on a Windows XP computer "c:\\zlib\\zlib113.zip" or on an Unix computer
+ "zlib/zlib113.zip".
+ If the zipfile cannot be opened (file don't exist or in not valid), the
+ return value is NULL.
+ Else, the return value is a unzFile Handle, usable with other function
+ of this unzip package.
+*/
+
+extern unzFile ZEXPORT unzOpen2 OF((const char *path,
+ zlib_filefunc_def* pzlib_filefunc_def));
+/*
+ Open a Zip file, like unzOpen, but provide a set of file low level API
+ for read/write the zip file (see ioapi.h)
+*/
+
+extern int ZEXPORT unzClose OF((unzFile file));
+/*
+ Close a ZipFile opened with unzipOpen.
+ If there is files inside the .Zip opened with unzOpenCurrentFile (see later),
+ these files MUST be closed with unzipCloseCurrentFile before call unzipClose.
+ return UNZ_OK if there is no problem. */
+
+extern int ZEXPORT unzGetGlobalInfo OF((unzFile file,
+ unz_global_info *pglobal_info));
+/*
+ Write info about the ZipFile in the *pglobal_info structure.
+ No preparation of the structure is needed
+ return UNZ_OK if there is no problem. */
+
+
+extern int ZEXPORT unzGetGlobalComment OF((unzFile file,
+ char *szComment,
+ uLong uSizeBuf));
+/*
+ Get the global comment string of the ZipFile, in the szComment buffer.
+ uSizeBuf is the size of the szComment buffer.
+ return the number of byte copied or an error code <0
+*/
+
+
+/***************************************************************************/
+/* Unzip package allow you browse the directory of the zipfile */
+
+extern int ZEXPORT unzGoToFirstFile OF((unzFile file));
+/*
+ Set the current file of the zipfile to the first file.
+ return UNZ_OK if there is no problem
+*/
+
+extern int ZEXPORT unzGoToNextFile OF((unzFile file));
+/*
+ Set the current file of the zipfile to the next file.
+ return UNZ_OK if there is no problem
+ return UNZ_END_OF_LIST_OF_FILE if the actual file was the latest.
+*/
+
+extern int ZEXPORT unzLocateFile OF((unzFile file,
+ const char *szFileName,
+ int iCaseSensitivity));
+/*
+ Try locate the file szFileName in the zipfile.
+ For the iCaseSensitivity signification, see unzStringFileNameCompare
+
+ return value :
+ UNZ_OK if the file is found. It becomes the current file.
+ UNZ_END_OF_LIST_OF_FILE if the file is not found
+*/
+
+
+/* ****************************************** */
+/* Ryan supplied functions */
+/* unz_file_info contain information about a file in the zipfile */
+typedef struct unz_file_pos_s
+{
+ uLong pos_in_zip_directory; /* offset in zip file directory */
+ uLong num_of_file; /* # of file */
+} unz_file_pos;
+
+extern int ZEXPORT unzGetFilePos(
+ unzFile file,
+ unz_file_pos* file_pos);
+
+extern int ZEXPORT unzGoToFilePos(
+ unzFile file,
+ unz_file_pos* file_pos);
+
+/* ****************************************** */
+
+extern int ZEXPORT unzGetCurrentFileInfo OF((unzFile file,
+ unz_file_info *pfile_info,
+ char *szFileName,
+ uLong fileNameBufferSize,
+ void *extraField,
+ uLong extraFieldBufferSize,
+ char *szComment,
+ uLong commentBufferSize));
+/*
+ Get Info about the current file
+ if pfile_info!=NULL, the *pfile_info structure will contain somes info about
+ the current file
+ if szFileName!=NULL, the filemane string will be copied in szFileName
+ (fileNameBufferSize is the size of the buffer)
+ if extraField!=NULL, the extra field information will be copied in extraField
+ (extraFieldBufferSize is the size of the buffer).
+ This is the Central-header version of the extra field
+ if szComment!=NULL, the comment string of the file will be copied in szComment
+ (commentBufferSize is the size of the buffer)
+*/
+
+/***************************************************************************/
+/* for reading the content of the current zipfile, you can open it, read data
+ from it, and close it (you can close it before reading all the file)
+ */
+
+extern int ZEXPORT unzOpenCurrentFile OF((unzFile file));
+/*
+ Open for reading data the current file in the zipfile.
+ If there is no error, the return value is UNZ_OK.
+*/
+
+extern int ZEXPORT unzOpenCurrentFilePassword OF((unzFile file,
+ const char* password));
+/*
+ Open for reading data the current file in the zipfile.
+ password is a crypting password
+ If there is no error, the return value is UNZ_OK.
+*/
+
+extern int ZEXPORT unzOpenCurrentFile2 OF((unzFile file,
+ int* method,
+ int* level,
+ int raw));
+/*
+ Same than unzOpenCurrentFile, but open for read raw the file (not uncompress)
+ if raw==1
+ *method will receive method of compression, *level will receive level of
+ compression
+ note : you can set level parameter as NULL (if you did not want known level,
+ but you CANNOT set method parameter as NULL
+*/
+
+extern int ZEXPORT unzOpenCurrentFile3 OF((unzFile file,
+ int* method,
+ int* level,
+ int raw,
+ const char* password));
+/*
+ Same than unzOpenCurrentFile, but open for read raw the file (not uncompress)
+ if raw==1
+ *method will receive method of compression, *level will receive level of
+ compression
+ note : you can set level parameter as NULL (if you did not want known level,
+ but you CANNOT set method parameter as NULL
+*/
+
+
+extern int ZEXPORT unzCloseCurrentFile OF((unzFile file));
+/*
+ Close the file in zip opened with unzOpenCurrentFile
+ Return UNZ_CRCERROR if all the file was read but the CRC is not good
+*/
+
+extern int ZEXPORT unzReadCurrentFile OF((unzFile file,
+ voidp buf,
+ unsigned len));
+/*
+ Read bytes from the current file (opened by unzOpenCurrentFile)
+ buf contain buffer where data must be copied
+ len the size of buf.
+
+ return the number of byte copied if somes bytes are copied
+ return 0 if the end of file was reached
+ return <0 with error code if there is an error
+ (UNZ_ERRNO for IO error, or zLib error for uncompress error)
+*/
+
+extern z_off_t ZEXPORT unztell OF((unzFile file));
+/*
+ Give the current position in uncompressed data
+*/
+
+extern int ZEXPORT unzeof OF((unzFile file));
+/*
+ return 1 if the end of file was reached, 0 elsewhere
+*/
+
+extern int ZEXPORT unzGetLocalExtrafield OF((unzFile file,
+ voidp buf,
+ unsigned len));
+/*
+ Read extra field from the current file (opened by unzOpenCurrentFile)
+ This is the local-header version of the extra field (sometimes, there is
+ more info in the local-header version than in the central-header)
+
+ if buf==NULL, it return the size of the local extra field
+
+ if buf!=NULL, len is the size of the buffer, the extra header is copied in
+ buf.
+ the return value is the number of bytes copied in buf, or (if <0)
+ the error code
+*/
+
+/***************************************************************************/
+
+/* Get the current file offset */
+extern uLong ZEXPORT unzGetOffset (unzFile file);
+
+/* Set the current file offset */
+extern int ZEXPORT unzSetOffset (unzFile file, uLong pos);
+
+
+int gf_unzip_probe(const char *zipfilename);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _unz_H */
--- /dev/null
+//This software module was originally developed by TelecomParisTech in the
+//course of the development of MPEG-U Widgets (ISO/IEC 23007-1) standard.
+//
+//This software module is an implementation of a part of one or
+//more MPEG-U Widgets (ISO/IEC 23007-1) tools as specified by the MPEG-U Widgets
+//(ISO/IEC 23007-1) standard. ISO/IEC gives users of the MPEG-U Widgets
+//(ISO/IEC 23007-1) free license to this software module or modifications
+//thereof for use in hardware or software products claiming conformance to
+//the MPEG-U Widgets (ISO/IEC 23007-1). Those intending to use this software
+//module in hardware or software products are advised that its use may
+//infringe existing patents.
+//The original developer of this software module and his/her company, the
+//subsequent editors and their companies, and ISO/IEC have no liability
+//for use of this software module or modifications thereof in an implementation.
+//Copyright is not released for non MPEG-U Widgets (ISO/IEC 23007-1) conforming
+//products.
+//Telecom ParisTech retains full right to use the code for his/her own purpose,
+//assign or donate the code to a third party and to inhibit third parties from
+//using the code for non MPEG-U Widgets (ISO/IEC 23007-1) conforming products.
+//
+//This copyright notice must be included in all copies or derivative works.
+//
+//Copyright (c) 2009.
+//
+// Alternatively, this software module may be redistributed and/or modified
+// it under the terms of the GNU Lesser General Public License as published by
+// the Free Software Foundation; either version 2, or (at your option)
+// any later version.
+//
+/////////////////////////////////////////////////////////////////////////////////
+
+/////////////////////////////////////////////////////////////////////////////////
+//
+// Authors:
+// Cyril Concolato, Telecom ParisTech
+// Jean Le Feuvre, Telecom ParisTech
+//
+/////////////////////////////////////////////////////////////////////////////////
+
+
+#include <gpac/internal/terminal_dev.h>
+#include <gpac/internal/scenegraph_dev.h>
+#include <gpac/nodes_svg.h>
+#include <gpac/constants.h>
+
+#ifdef GPAC_HAS_SPIDERMONKEY
+
+typedef struct
+{
+ GF_Scene *scene;
+ u8 oti;
+ char *file_name;
+ u32 file_size;
+ Bool loaded;
+} WgtLoad;
+
+static GF_Err WGT_ProcessData(GF_SceneDecoder *plug, const char *inBuffer, u32 inBufferLength,
+ u16 ES_ID, u32 stream_time, u32 mmlevel)
+{
+ GF_Err e = GF_OK;
+ WgtLoad *wgtload = (WgtLoad *)plug->privateStack;
+
+ if (stream_time==(u32)-1) {
+ gf_sg_reset(wgtload->scene->graph);
+ return GF_OK;
+ }
+
+ switch (wgtload->oti) {
+ case GPAC_OTI_PRIVATE_SCENE_WGT:
+ if (wgtload->file_name && !wgtload->loaded) {
+ const char *path, *wmpath;
+ char *tmp;
+ GF_Node *n, *root;
+ GF_FieldInfo info;
+ FILE *jsfile;
+ GF_ChildNodeItem *last;
+
+ wgtload->loaded = 1;
+
+ gf_sg_add_namespace(wgtload->scene->graph, "http://www.w3.org/2000/svg", NULL);
+ gf_sg_add_namespace(wgtload->scene->graph, "http://www.w3.org/1999/xlink", "xlink");
+ gf_sg_add_namespace(wgtload->scene->graph, "http://www.w3.org/2001/xml-events", "ev");
+ gf_sg_set_scene_size_info(wgtload->scene->graph, 800, 600, 1);
+
+ /* modify the scene with an Inline/Animation pointing to the widget start file URL */
+ n = root = gf_node_new(wgtload->scene->graph, TAG_SVG_svg);
+ gf_node_register(root, NULL);
+ gf_sg_set_root_node(wgtload->scene->graph, root);
+ gf_node_get_attribute_by_tag(n, TAG_SVG_ATT_viewBox, 1, 0, &info);
+ gf_svg_parse_attribute(n, &info, "0 0 320 240", 0);
+ gf_node_get_attribute_by_name(n, "xmlns", 0, 1, 0, &info);
+ gf_svg_parse_attribute(n, &info, "http://www.w3.org/2000/svg", 0);
+/*
+ gf_sg_set_scene_size_info(wgtload->scene->graph, 800, 600, 1);
+ gf_node_get_attribute_by_tag(n, TAG_SVG_ATT_width, 1, 0, &info);
+ gf_svg_parse_attribute(n, &info, "800", 0);
+ gf_node_get_attribute_by_tag(n, TAG_SVG_ATT_height, 1, 0, &info);
+ gf_svg_parse_attribute(n, &info, "600", 0);
+*/
+ gf_node_init(n);
+
+ n = gf_node_new(wgtload->scene->graph, TAG_SVG_animation);
+ gf_node_set_id(n, 1, "w_anim");
+ gf_node_register(n, root);
+ gf_node_list_add_child_last(&((GF_ParentNode *)root)->children, n, &last);
+ gf_node_get_attribute_by_tag(n, TAG_SVG_ATT_width, 1, 0, &info);
+ gf_svg_parse_attribute(n, &info, "320", 0);
+ gf_node_get_attribute_by_tag(n, TAG_SVG_ATT_height, 1, 0, &info);
+ gf_svg_parse_attribute(n, &info, "240", 0);
+ gf_node_init(n);
+
+ tmp = wgtload->file_name;
+ while ((tmp = strchr(tmp, '\\'))) {
+ tmp[0] = '/';
+ tmp++;
+ }
+
+ n = gf_node_new(wgtload->scene->graph, TAG_SVG_script);
+ gf_node_register(n, root);
+ gf_node_list_add_child_last(&((GF_ParentNode *)root)->children, n, &last);
+ path = gf_modules_get_option((GF_BaseInterface *)plug, "Widgets", "WidgetLoadScript");
+ jsfile = path ? gf_f64_open(path, "rt") : NULL;
+ if (jsfile) {
+ fclose(jsfile);
+ gf_node_get_attribute_by_tag(n, TAG_XLINK_ATT_href, 1, 0, &info);
+ gf_svg_parse_attribute(n, &info, (char *) path, 0);
+ } else {
+ const char *load_fun = "function load_widget(wid_url) {\n"
+ " var wid = WidgetManager.load(wid_url);\n"
+ " var anim = document.getElementById('w_anim');\n"
+ " if (wid != null) {\n"
+ " wid.activate(anim);"
+ " anim.setAttributeNS('http://www.w3.org/1999/xlink', 'href', wid.main);\n"
+ " } else {\n"
+ " alert('Widget ' + wid_url + ' is not valid');\n"
+ " }\n"
+ "}\n";
+
+ gf_dom_add_text_node(n, gf_strdup(load_fun) );
+ }
+ gf_node_init(n);
+
+
+ wmpath = gf_modules_get_option((GF_BaseInterface *)plug, "Widgets", "WidgetManagerScript");
+ jsfile = wmpath ? gf_f64_open(wmpath, "rt") : NULL;
+ if (jsfile) {
+ fclose(jsfile);
+ n = gf_node_new(wgtload->scene->graph, TAG_SVG_script);
+ gf_node_register(n, root);
+ gf_node_list_add_child_last(&((GF_ParentNode *)root)->children, n, &last);
+ gf_node_get_attribute_by_tag(n, TAG_XLINK_ATT_href, 1, 0, &info);
+ gf_svg_parse_attribute(n, &info, (char *) wmpath, 0);
+ gf_node_init(n);
+
+ n = gf_node_new(wgtload->scene->graph, TAG_SVG_script);
+ gf_node_register(n, root);
+ gf_node_list_add_child_last(&((GF_ParentNode *)root)->children, n, &last);
+ gf_dom_add_text_node(n, gf_strdup("widget_manager_init();") );
+ gf_node_init(n);
+ }
+
+ tmp = gf_malloc(sizeof(char) * (strlen(wgtload->file_name)+50) );
+ sprintf(tmp, "load_widget(\"%s\");\n", wgtload->file_name);
+
+ n = gf_node_new(wgtload->scene->graph, TAG_SVG_script);
+ gf_node_register(n, root);
+ gf_node_list_add_child_last(&((GF_ParentNode *)root)->children, n, &last);
+ gf_dom_add_text_node(n, gf_strdup(tmp) );
+ gf_free(tmp);
+
+ gf_node_init(n);
+
+ if ((wgtload->scene->graph_attached!=1) && (gf_sg_get_root_node(wgtload->scene->graph)!=NULL) ) {
+ gf_scene_attach_to_compositor(wgtload->scene);
+ e = GF_EOS;
+ }
+ }
+ break;
+
+ default:
+ return GF_BAD_PARAM;
+ }
+ return e;
+}
+
+static GF_Err WGT_AttachScene(GF_SceneDecoder *plug, GF_Scene *scene, Bool is_scene_decoder)
+{
+ WgtLoad *wgtload = (WgtLoad *)plug->privateStack;
+ wgtload->scene = scene;
+ return GF_OK;
+}
+
+static GF_Err WGT_ReleaseScene(GF_SceneDecoder *plug)
+{
+ WgtLoad *wgtload = (WgtLoad *)plug->privateStack;
+ wgtload->scene = NULL;
+ return GF_OK;
+}
+
+static GF_Err WGT_AttachStream(GF_BaseDecoder *plug, GF_ESD *esd)
+{
+ GF_BitStream *bs;
+ WgtLoad *wgtload = (WgtLoad *)plug->privateStack;
+ if (esd->decoderConfig->upstream) return GF_NOT_SUPPORTED;
+
+ /* decSpecInfo is not null only when reading from an WGT file (local or distant, cached or not) */
+ switch (esd->decoderConfig->objectTypeIndication) {
+ case GPAC_OTI_PRIVATE_SCENE_WGT:
+ default:
+ if (!esd->decoderConfig->decoderSpecificInfo) return GF_NON_COMPLIANT_BITSTREAM;
+ bs = gf_bs_new(esd->decoderConfig->decoderSpecificInfo->data, esd->decoderConfig->decoderSpecificInfo->dataLength, GF_BITSTREAM_READ);
+ wgtload->file_size = gf_bs_read_u32(bs);
+ gf_bs_del(bs);
+ wgtload->file_name = (char *) gf_malloc(sizeof(char)*(1 + esd->decoderConfig->decoderSpecificInfo->dataLength - sizeof(u32)) );
+ memcpy(wgtload->file_name, esd->decoderConfig->decoderSpecificInfo->data + sizeof(u32), esd->decoderConfig->decoderSpecificInfo->dataLength - sizeof(u32) );
+ wgtload->file_name[esd->decoderConfig->decoderSpecificInfo->dataLength - sizeof(u32) ] = 0;
+ break;
+ }
+ wgtload->oti = esd->decoderConfig->objectTypeIndication;
+ return GF_OK;
+}
+
+static GF_Err WGT_DetachStream(GF_BaseDecoder *plug, u16 ES_ID)
+{
+ WgtLoad *wgtload = (WgtLoad *)plug->privateStack;
+ if (wgtload->file_name) gf_free(wgtload->file_name);
+ wgtload->file_name = NULL;
+ return GF_OK;
+}
+
+const char *WGT_GetName(struct _basedecoder *plug)
+{
+ return "GPAC W3C Widget Loader";
+}
+
+static u32 WGT_CanHandleStream(GF_BaseDecoder *ifce, u32 StreamType, GF_ESD *esd, u8 PL)
+{
+ /*don't reply to media type query*/
+ if (!esd) return GF_CODEC_NOT_SUPPORTED;
+
+ if (StreamType==GF_STREAM_PRIVATE_SCENE) {
+ if (esd->decoderConfig->objectTypeIndication==GPAC_OTI_PRIVATE_SCENE_WGT) return GF_CODEC_SUPPORTED;
+ return GF_CODEC_NOT_SUPPORTED;
+ }
+ return GF_CODEC_NOT_SUPPORTED;
+}
+
+static GF_Err WGT_GetCapabilities(GF_BaseDecoder *plug, GF_CodecCapability *cap)
+{
+ cap->cap.valueInt = 0;
+ if (cap->CapCode==GF_CODEC_PADDING_BYTES) {
+ /* Adding one byte of padding for \r\n problems*/
+ cap->cap.valueInt = 1;
+ return GF_OK;
+ }
+ return GF_NOT_SUPPORTED;
+}
+
+static GF_Err WGT_SetCapabilities(GF_BaseDecoder *plug, const GF_CodecCapability capability)
+{
+ return GF_OK;
+}
+
+/*interface create*/
+GF_BaseInterface *LoadWidgetReader()
+{
+ WgtLoad *wgtload;
+ GF_SceneDecoder *sdec;
+
+ GF_SAFEALLOC(sdec, GF_SceneDecoder)
+ GF_REGISTER_MODULE_INTERFACE(sdec, GF_SCENE_DECODER_INTERFACE, "GPAC W3C Widget Loader", "gpac distribution");
+
+ GF_SAFEALLOC(wgtload, WgtLoad);
+ sdec->privateStack = wgtload;
+ sdec->AttachStream = WGT_AttachStream;
+ sdec->CanHandleStream = WGT_CanHandleStream;
+ sdec->DetachStream = WGT_DetachStream;
+ sdec->AttachScene = WGT_AttachScene;
+ sdec->ReleaseScene = WGT_ReleaseScene;
+ sdec->ProcessData = WGT_ProcessData;
+ sdec->GetName = WGT_GetName;
+ sdec->SetCapabilities = WGT_SetCapabilities;
+ sdec->GetCapabilities = WGT_GetCapabilities;
+ return (GF_BaseInterface *)sdec;
+}
+
+
+/*interface destroy*/
+void ShutdownWidgetReader(GF_BaseInterface *ifce)
+{
+ GF_SceneDecoder *sdec = (GF_SceneDecoder *)ifce;
+ WgtLoad *wgtload;
+ if (!ifce)
+ return;
+ wgtload = (WgtLoad *) sdec->privateStack;
+ if (wgtload)
+ gf_free(wgtload);
+ sdec->privateStack = NULL;
+ gf_free(sdec);
+}
+
+#endif /*GPAC_HAS_SPIDERMONKEY*/
--- /dev/null
+var wid = null;
+var xmlns_xlink = 'http://www.w3.org/1999/xlink';
+
+function debug(s) {
+ alert('[Widget Loader] '+s);
+}
+
+function add_text_span(parent, string) {
+ var span = document.createElement('tspan');
+ span.textContent = string;
+ parent.appendChild(span);
+ parent.appendChild(document.createElement('tbreak'));
+}
+
+function load_widget(wid_url) {
+ debug('Loading Widget: '+wid_url);
+ wid = WidgetManager.load(wid_url);
+ var anim = document.getElementById('w_anim');
+ width = 320;
+ height = 240;
+ anim.setAttribute('height', height/3);
+
+ var info = document.createElement('textArea');
+ document.documentElement.appendChild(info);
+ info.setAttribute('y', height/3);
+ info.setAttribute('width', width);
+
+ info.setAttribute('font-size', '7');
+ info.setAttribute('font-family', 'Arial Unicode MS');
+ if (wid != null) {
+ debug('Loading scene: '+wid.main);
+ anim.setAttributeNS(xmlns_xlink, 'href', wid.main);
+ add_text_span(info, 'Widget Metadata');
+ add_text_span(info, 'UA Locale: \'' + gpac.getOption('Systems', 'Language2CC') + '\'');
+ add_text_span(info, 'widget src (abs.): \'' + wid.url + '\'');
+ add_text_span(info, 'config src (abs.): \'' + wid.manifest + '\'');
+ add_text_span(info, 'content src (rel.&loc./abs.): \''+wid.main+'\' / \''+wid.localizedSrc+'\' ('+wid.mainMimeType+';'+wid.mainEncoding+')');
+ add_text_span(info, 'id: \'' + wid.identifier + '\'');
+ add_text_span(info, 'shortname/name: \''+wid.shortName+ '\' / \''+wid.name+'\'');
+ add_text_span(info, 'version: \''+wid.version+'\'');
+ add_text_span(info, 'license/href: \''+wid.license+'\' / \''+wid.licenseHref+'\'');
+ add_text_span(info, 'description: \''+wid.description+'\'');
+ add_text_span(info, 'author (name/email/href): \''+wid.authorName+ '\' / \''+wid.authorEmail +'\' / \''+wid.authorHref+'\'');
+ var s = 'icons src (rel.&loc./abs.): ';
+ for (var i=0; i<wid.icons.length; i++) {
+ if (i) s += ' , ';
+ s += '\'' + wid.icons[i].src + '\' / \'' + wid.icons[i].relocated_src + '\'' + ' ('+wid.icons[i].width+'x'+wid.icons[i].height+')';
+ }
+ add_text_span(info, s);
+
+ s = 'preferences: ';
+ for (var i=0; i<wid.preferences.length; i++) {
+ var p = wid.preferences[i];
+ if (i) s += ' , ';
+ s += '' + p.name + '=\'' + p.value + '\' (ro:'+p.readonly+')';
+ }
+ add_text_span(info, s);
+
+ s = 'features: ';
+ add_text_span(info, s);
+
+ for (var i=0; i<wid.features.length; i++) {
+ var f = wid.features[i];
+ s = 'feature: ';
+ s += '' + f.name + '(' + f.required + ')';
+ add_text_span(info, s);
+ if (f.params.length) {
+ s = '-params: ';
+ for (var j=0; j<f.params.length; j++) {
+ var p = f.params[j];
+ if (j != 0) s += ' , ';
+ s += '' + p.name + '=\'' + p.value + '\'';
+ }
+ add_text_span(info, s);
+ }
+ }
+
+ add_text_span(info, 'size: '+wid.defaultWidth+'x'+wid.defaultHeight);
+ add_text_span(info, 'viewmodes: \''+wid.viewmodes+'\'');
+ } else {
+ debug('Invalid Widget');
+ info.textContent = 'Invalid widget - no info available';
+ }
+}
--- /dev/null
+//This software module was originally developed by TelecomParisTech in the
+//course of the development of MPEG-U Widgets (ISO/IEC 23007-1) standard.
+//
+//This software module is an implementation of a part of one or
+//more MPEG-U Widgets (ISO/IEC 23007-1) tools as specified by the MPEG-U Widgets
+//(ISO/IEC 23007-1) standard. ISO/IEC gives users of the MPEG-U Widgets
+//(ISO/IEC 23007-1) free license to this software module or modifications
+//thereof for use in hardware or software products claiming conformance to
+//the MPEG-U Widgets (ISO/IEC 23007-1). Those intending to use this software
+//module in hardware or software products are advised that its use may
+//infringe existing patents.
+//The original developer of this software module and his/her company, the
+//subsequent editors and their companies, and ISO/IEC have no liability
+//for use of this software module or modifications thereof in an implementation.
+//Copyright is not released for non MPEG-U Widgets (ISO/IEC 23007-1) conforming
+//products.
+//Telecom ParisTech retains full right to use the code for his/her own purpose,
+//assign or donate the code to a third party and to inhibit third parties from
+//using the code for non MPEG-U Widgets (ISO/IEC 23007-1) conforming products.
+//
+//This copyright notice must be included in all copies or derivative works.
+//
+//Copyright (c) 2009.
+//
+// Alternatively, this software module may be redistributed and/or modified
+// it under the terms of the GNU Lesser General Public License as published by
+// the Free Software Foundation; either version 2, or (at your option)
+// any later version.
+//
+/////////////////////////////////////////////////////////////////////////////////
+
+
+/////////////////////////////////////////////////////////////////////////////////
+//
+// Authors:
+// Jean Le Feuvre, Telecom ParisTech
+//
+/////////////////////////////////////////////////////////////////////////////////
+
+
+#include "widgetman.h"
+
+#ifdef GPAC_HAS_SPIDERMONKEY
+
+JSBool SMJS_FUNCTION(widget_has_feature)
+{
+ char *feat_name;
+ SMJS_OBJ
+ SMJS_ARGS
+ GF_WidgetInstance *wid = (GF_WidgetInstance *)JS_GetPrivate(c, obj);
+ if (!wid) return JS_FALSE;
+
+ if (!argc || !JSVAL_IS_STRING(argv[0])) return JS_TRUE;
+
+ feat_name = SMJS_CHARS(c, argv[0]);
+ SMJS_SET_RVAL( BOOLEAN_TO_JSVAL( JS_FALSE ) );
+
+ if (!strcmp(feat_name, "urn:mpeg:systems:mpeg-u:2009")) SMJS_SET_RVAL( BOOLEAN_TO_JSVAL( JS_TRUE ));
+ SMJS_FREE(c, feat_name);
+ return JS_TRUE;
+}
+
+JSBool SMJS_FUNCTION(widget_open_url)
+{
+ GF_Event evt;
+ SMJS_OBJ
+ SMJS_ARGS
+ GF_WidgetInstance *wid = (GF_WidgetInstance *)JS_GetPrivate(c, obj);
+ if (!wid || !argc || !JSVAL_IS_STRING(argv[0])) return JS_TRUE;
+
+ memset(&evt, 0, sizeof(GF_Event));
+ evt.type = GF_EVENT_NAVIGATE;
+ evt.navigate.to_url = SMJS_CHARS(c, argv[0]);
+ gf_term_send_event(wid->widget->wm->term, &evt);
+ SMJS_FREE(c, (char *)evt.navigate.to_url);
+
+ return JS_TRUE;
+}
+
+JSBool SMJS_FUNCTION(widget_get_attention)
+{
+ jsval fval;
+ SMJS_OBJ
+ GF_WidgetInstance *wid = (GF_WidgetInstance *)JS_GetPrivate(c, obj);
+ if (!wid) return JS_TRUE;
+
+ if ((JS_LookupProperty(c, wid->widget->wm->obj, "getAttention", &fval)==JS_TRUE) && JSVAL_IS_OBJECT(fval)) {
+ jsval args[1];
+ args[0] = OBJECT_TO_JSVAL(wid->obj);
+ JS_CallFunctionValue(c, wid->widget->wm->obj, fval, 1, args, SMJS_GET_RVAL);
+ }
+ return JS_TRUE;
+}
+
+JSBool SMJS_FUNCTION(widget_show_notification)
+{
+ jsval fval;
+ SMJS_OBJ
+ SMJS_ARGS
+ GF_WidgetInstance *wid = (GF_WidgetInstance *)JS_GetPrivate(c, obj);
+ if (!wid) return JS_TRUE;
+
+ if ((JS_LookupProperty(c, wid->widget->wm->obj, "showNotification", &fval)==JS_TRUE) && JSVAL_IS_OBJECT(fval)) {
+ jsval *vars;
+ u32 i;
+ vars = gf_malloc(sizeof(jsval)*(argc+1));
+ vars[0] = OBJECT_TO_JSVAL(wid->obj);
+ for (i=0; i<argc; i++)
+ vars[i+1] = argv[i];
+
+ JS_CallFunctionValue(c, wid->widget->wm->obj, fval, argc+1, vars, SMJS_GET_RVAL);
+ }
+ return JS_TRUE;
+}
+
+
+static JSBool SMJS_FUNCTION(widget_call_message_reply_callback)
+{
+ JSObject *list;
+ jsval *vals, fval;
+ u32 i, count;
+ SMJS_OBJ
+ SMJS_ARGS
+ GF_WidgetMessage *msg = JS_GetPrivate(c, obj);
+ if (!msg || !argc || !JSVAL_IS_OBJECT(argv[0]) ) return JS_FALSE;
+
+ if ((JS_LookupProperty(c, obj, "replyCallback", &fval)==JS_TRUE) && JSVAL_IS_OBJECT(fval)) {
+ list = JSVAL_TO_OBJECT(argv[0]);
+ JS_GetArrayLength(c, list, (jsuint*) &count);
+ vals = gf_malloc(sizeof(jsval)*(count+1));
+ vals[0] = OBJECT_TO_JSVAL(obj);
+ for (i=0; i<count; i++) {
+ JS_GetElement(c, list, (jsint) i, &vals[i+1]);
+ }
+ JS_CallFunctionValue(c, obj, fval, count, vals, SMJS_GET_RVAL);
+ gf_free(vals);
+ }
+ return JS_TRUE;
+}
+
+static JSBool SMJS_FUNCTION(widget_message_handler_factory)
+{
+ char *msg_name;
+ u32 i, count;
+ SMJS_OBJ
+ SMJS_ARGS
+ GF_WidgetInterfaceInstance *bifce = (GF_WidgetInterfaceInstance *)JS_GetPrivate(c, obj);
+ if (!bifce) return JS_FALSE;
+
+ if (!argc) return JS_FALSE;
+ if (!JSVAL_IS_STRING(argv[0])) return JS_FALSE;
+
+ msg_name = SMJS_CHARS(c, argv[0]);
+ if (!msg_name ) return JS_FALSE;
+
+ SMJS_SET_RVAL( JSVAL_NULL );
+ count = gf_list_count(bifce->ifce->messages);
+ for (i=0; i<count; i++) {
+ GF_WidgetMessage *msg = gf_list_get(bifce->ifce->messages, i);
+ if (!strcmp(msg->name, msg_name)) {
+ JSObject *an_obj = JS_NewObject(c, &bifce->wid->widget->wm->widgetAnyClass, 0, 0);
+ JS_SetPrivate(c, an_obj, msg);
+ JS_DefineProperty(c, an_obj, "msgName", STRING_TO_JSVAL( JS_NewStringCopyZ(c, msg->name) ), 0, 0, JSPROP_READONLY | JSPROP_PERMANENT);
+ JS_DefineProperty(c, an_obj, "interfaceHandler", OBJECT_TO_JSVAL( obj ), 0, 0, JSPROP_READONLY | JSPROP_PERMANENT);
+ JS_DefineFunction(c, an_obj, "onInvokeReply", widget_call_message_reply_callback, 1, 0);
+
+ if ((argc==2) && JSVAL_IS_OBJECT(argv[1]) && !JSVAL_IS_NULL(argv[1]))
+ JS_DefineProperty(c, an_obj, "replyCallback", argv[1], 0, 0, JSPROP_READONLY | JSPROP_PERMANENT);
+
+ SMJS_SET_RVAL( OBJECT_TO_JSVAL(an_obj) );
+ }
+ }
+ SMJS_FREE(c, msg_name);
+ return JS_TRUE;
+}
+static JSBool SMJS_FUNCTION(widget_invoke_message)
+{
+ jsval oval;
+ GF_WidgetMessage *msg = NULL;
+ SMJS_OBJ
+ SMJS_ARGS
+ GF_WidgetInterfaceInstance *bifce = (GF_WidgetInterfaceInstance *)JS_GetPrivate(c, obj);
+ if (!bifce) return JS_FALSE;
+
+ SMJS_SET_RVAL( JSVAL_NULL );
+
+ if (!JSVAL_IS_OBJECT(argv[0])) return JS_FALSE;
+ if (JSVAL_IS_NULL(argv[0])) return JS_FALSE;
+ msg = (GF_WidgetMessage *)JS_GetPrivate(c, JSVAL_TO_OBJECT(argv[0]) );
+ if (!msg) return JS_FALSE;
+
+ /*look for JS Callback "invoke" in the widget manager script*/
+ if (JS_LookupProperty(c, bifce->ifce->obj, "invoke", &oval)==JS_TRUE) {
+ if (JSVAL_IS_OBJECT(oval)) {
+ JS_CallFunctionValue(bifce->wid->widget->wm->ctx, bifce->ifce->obj, oval, argc, argv, SMJS_GET_RVAL );
+ }
+ }
+
+ return JS_TRUE;
+}
+
+static JSBool SMJS_FUNCTION(widget_invoke_message_reply)
+{
+ jsval oval;
+ SMJS_OBJ
+ SMJS_ARGS
+ GF_WidgetMessage *msg = NULL;
+ GF_WidgetInterfaceInstance *bifce = (GF_WidgetInterfaceInstance *)JS_GetPrivate(c, obj);
+ if (!bifce) return JS_FALSE;
+
+ SMJS_SET_RVAL( JSVAL_NULL );
+
+ if (!JSVAL_IS_OBJECT(argv[0])) return JS_FALSE;
+ if (JSVAL_IS_NULL(argv[0])) return JS_FALSE;
+ msg = (GF_WidgetMessage *)JS_GetPrivate(c, JSVAL_TO_OBJECT(argv[0]) );
+ if (!msg) return JS_FALSE;
+
+ /*look for JS Callback "invokeReply" in the widget manager script*/
+ if (JS_LookupProperty(c, bifce->ifce->obj, "invokeReply", &oval)==JS_TRUE) {
+ if (JSVAL_IS_OBJECT(oval)) {
+ JS_CallFunctionValue(bifce->wid->widget->wm->ctx, bifce->ifce->obj, oval, argc, argv, SMJS_GET_RVAL);
+ }
+ }
+ return JS_TRUE;
+}
+
+static void widget_interface_js_bind(JSContext *c, GF_WidgetInterfaceInstance *ifce)
+{
+ if (!ifce->obj) {
+ ifce->obj = JS_NewObject(c, &ifce->wid->widget->wm->widgetAnyClass, 0, 0);
+ JS_SetPrivate(c, ifce->obj, ifce);
+ gf_js_add_root(c, &ifce->obj, GF_JSGC_OBJECT);
+ JS_DefineProperty(c, ifce->obj, "type", STRING_TO_JSVAL( JS_NewStringCopyZ(c, ifce->ifce->type) ), 0, 0, JSPROP_READONLY | JSPROP_PERMANENT);
+ JS_DefineProperty(c, ifce->obj, "bound", STRING_TO_JSVAL( JS_NewStringCopyZ(c, ifce->hostname) ), 0, 0, JSPROP_READONLY | JSPROP_PERMANENT);
+ JS_DefineFunction(c, ifce->obj, "invoke", widget_invoke_message, 1, 0);
+ JS_DefineFunction(c, ifce->obj, "msgHandlerFactory", widget_message_handler_factory, 1, 0);
+ JS_DefineFunction(c, ifce->obj, "invokeReply", widget_invoke_message_reply, 1, 0);
+ }
+}
+
+static JSBool SMJS_FUNCTION(widget_get_interfaces)
+{
+ u32 i, count;
+ char *ifce_name;
+ JSObject *list;
+ jsuint idx;
+ jsval v;
+ SMJS_OBJ
+ SMJS_ARGS
+ GF_WidgetInstance *wid = (GF_WidgetInstance *)JS_GetPrivate(c, obj);
+ if (!wid) return JS_FALSE;
+
+ if (!argc || !JSVAL_IS_STRING(argv[0])) return JS_TRUE;
+ ifce_name = SMJS_CHARS(c, argv[0]);
+
+ list = JS_NewArrayObject(c, 0, 0);
+
+ count = gf_list_count(wid->bound_ifces);
+ for (i=0; i<count; i++) {
+ GF_WidgetInterfaceInstance *ifce = gf_list_get(wid->bound_ifces, i);
+ if (strcmp(ifce->ifce->type, ifce_name)) continue;
+
+ widget_interface_js_bind(c, ifce);
+
+ JS_GetArrayLength(c, list, &idx);
+ v = OBJECT_TO_JSVAL(ifce->obj);
+ JS_SetElement(c, list, idx, &v);
+ }
+ SMJS_SET_RVAL( OBJECT_TO_JSVAL(list) );
+ SMJS_FREE(c, ifce_name);
+ return JS_TRUE;
+}
+
+static JSBool SMJS_FUNCTION_EXT(widget_activate_component, Bool is_deactivate)
+{
+ u32 i, count;
+ char *comp_id;
+ SMJS_OBJ
+ SMJS_ARGS
+ GF_WidgetInstance *wid = (GF_WidgetInstance *)JS_GetPrivate(c, obj);
+ if (!wid) return JS_FALSE;
+
+ if (!argc || !JSVAL_IS_STRING(argv[0])) return JS_TRUE;
+ comp_id = SMJS_CHARS(c, argv[0]);
+
+ count = gf_list_count(wid->widget->main->components);
+ for (i=0; i<count; i++) {
+ GF_WidgetComponent *comp = gf_list_get(wid->widget->main->components, i);
+ if (!comp->id || strcmp(comp->id, comp_id)) continue;
+
+ if (is_deactivate) {
+ wm_deactivate_component(c, wid, comp, NULL);
+ } else {
+ wm_activate_component(c, wid, comp, 0);
+ }
+ break;
+ }
+ SMJS_FREE(c, comp_id);
+ return JS_TRUE;
+}
+
+static JSBool SMJS_FUNCTION(widget_activate_widget)
+{
+ return widget_activate_component(SMJS_CALL_ARGS, 0);
+}
+
+static JSBool SMJS_FUNCTION(widget_deactivate_widget)
+{
+ return widget_activate_component(SMJS_CALL_ARGS, 1);
+}
+
+void widget_on_interface_bind(GF_WidgetInterfaceInstance *ifce, Bool unbind)
+{
+ jsval funval, rval, argv[1];
+
+ const char *fun_name = unbind ? "onInterfaceUnbind" : "onInterfaceBind";
+ if (!ifce || !ifce->wid || !ifce->wid->scene_context) return;
+
+ /*look for JS Callback "invoke" in the widget manager script*/
+ if (JS_LookupProperty(ifce->wid->scene_context, ifce->wid->scene_obj, fun_name, &funval)!=JS_TRUE)
+ return;
+ if (!JSVAL_IS_OBJECT(funval)) return;
+
+ widget_interface_js_bind(ifce->wid->widget->wm->ctx, ifce);
+ argv[0] = OBJECT_TO_JSVAL(ifce->obj);
+ JS_CallFunctionValue(ifce->wid->widget->wm->ctx, ifce->ifce->obj, funval, 1, argv, &rval);
+
+}
+
+JSBool widget_getProperty(JSContext *c, JSObject *obj, SMJS_PROP_GETTER, jsval *rval)
+{
+ const char *opt;
+ char *prop_name;
+ GF_WidgetInstance *wid = (GF_WidgetInstance *)JS_GetPrivate(c, obj);
+ if (!wid) return JS_FALSE;
+
+ if (!SMJS_ID_IS_STRING(id)) return JS_TRUE;
+ prop_name = SMJS_CHARS_FROM_STRING(c, SMJS_ID_TO_STRING(id));
+ if (!prop_name) return JS_FALSE;
+
+ if (!strcmp(prop_name, "viewMode")) {
+ *rval = STRING_TO_JSVAL( JS_NewStringCopyZ(c, "floating") );
+ }
+ else if (!strcmp(prop_name, "locale")) {
+ opt = gf_cfg_get_key(wid->widget->wm->term->user->config, "Systems", "Language2CC");
+ if (!opt) opt = "und";
+ *rval = STRING_TO_JSVAL( JS_NewStringCopyZ(c, opt) );
+ }
+ else if (!strcmp(prop_name, "identifier")) {
+ if (wid->widget->identifier) *rval = STRING_TO_JSVAL( JS_NewStringCopyZ(c, wid->widget->identifier) );
+ }
+ else if (!strcmp(prop_name, "authorName")) {
+ if (wid->widget->authorName) *rval = STRING_TO_JSVAL( JS_NewStringCopyZ(c, wid->widget->authorName) );
+ }
+ else if (!strcmp(prop_name, "authorEmail")) {
+ if (wid->widget->authorEmail) *rval = STRING_TO_JSVAL( JS_NewStringCopyZ(c, wid->widget->authorEmail) );
+ }
+ else if (!strcmp(prop_name, "authorHref")) {
+ if (wid->widget->authorHref) *rval = STRING_TO_JSVAL( JS_NewStringCopyZ(c, wid->widget->authorHref) );
+ }
+ else if (!strcmp(prop_name, "name")) {
+ if (wid->widget->name) *rval = STRING_TO_JSVAL( JS_NewStringCopyZ(c, wid->widget->name) );
+ }
+ else if (!strcmp(prop_name, "version")) {
+ if (wid->widget->version) *rval = STRING_TO_JSVAL( JS_NewStringCopyZ(c, wid->widget->version) );
+ }
+ else if (!strcmp(prop_name, "description")) {
+ if (wid->widget->description) *rval = STRING_TO_JSVAL( JS_NewStringCopyZ(c, wid->widget->description) );
+ }
+ else if (!strcmp(prop_name, "width")) {
+ opt = gf_cfg_get_key(wid->widget->wm->term->user->config, wid->secname, "width");
+ *rval = INT_TO_JSVAL( (opt ? atoi(opt) : 0) );
+ }
+ else if (!strcmp(prop_name, "height")) {
+ opt = gf_cfg_get_key(wid->widget->wm->term->user->config, wid->secname, "height");
+ *rval = INT_TO_JSVAL( (opt ? atoi(opt) : 0) );
+ }
+ else if (!strcmp(prop_name, "preferences")) {
+ }
+ SMJS_FREE(c, prop_name);
+ return JS_TRUE;
+}
+
+JSBool widget_setProperty(JSContext *c, JSObject *obj, SMJS_PROP_SETTER, jsval *vp)
+{
+ return JS_TRUE;
+}
+
+void widget_load(GF_WidgetManager *wm, GF_SceneGraph *scene, JSContext *c, JSObject *global, Bool unload)
+{
+ u32 i, count;
+ GF_WidgetInstance *wi;
+
+ /*Is this scenegraph a widget or not ? To find out, browse all widget instances*/
+ i=0;
+ while ((wi = gf_list_enum(wm->widget_instances, &i))) {
+ if (!wi->scene || (wi->scene != scene)) continue;
+ break;
+ }
+ if (!wi) return;
+
+ /*OK we found our widget*/
+
+ if (unload) {
+ /*detach all bound interfaces from this script*/
+ count = gf_list_count(wi->bound_ifces);
+ for (i=0; i<count; i++) {
+ GF_WidgetInterfaceInstance *ifce = gf_list_get(wi->bound_ifces, i);
+ if (ifce->obj) {
+ JS_SetPrivate(c, ifce->obj, NULL);
+ gf_js_remove_root(c, &ifce->obj, GF_JSGC_OBJECT);
+ ifce->obj = NULL;
+ }
+ }
+ return;
+ } else {
+
+ JSPropertySpec widgetClassProps[] = {
+ {0, 0, 0, 0, 0}
+ };
+ JSFunctionSpec widgetClassFuncs[] = {
+ /*W3C*/
+ SMJS_FUNCTION_SPEC("has_feature", widget_has_feature, 1),
+ SMJS_FUNCTION_SPEC("openURL", widget_open_url, 1),
+ SMJS_FUNCTION_SPEC("getAttention", widget_get_attention, 0),
+ SMJS_FUNCTION_SPEC("showNotification", widget_show_notification, 0),
+ /*MPEG*/
+ SMJS_FUNCTION_SPEC("getInterfaceHandlersByType", widget_get_interfaces, 1),
+ SMJS_FUNCTION_SPEC("activateComponentWidget", widget_activate_widget, 1),
+ SMJS_FUNCTION_SPEC("deactivateComponentWidget", widget_deactivate_widget, 1),
+ SMJS_FUNCTION_SPEC(0, 0, 0)
+ };
+
+ JS_InitClass(c, global, 0, &wm->widgetClass, 0, 0,widgetClassProps, widgetClassFuncs, 0, 0);
+
+
+ wi->scene_obj = JS_DefineObject(c, global, "widget", &wm->widgetClass, 0, 0);
+ //JS_AliasProperty(c, global, "widget", "MPEGWidget");
+ JS_SetPrivate(c, wi->scene_obj, wi);
+ /*and remember the script*/
+ wi->scene_context = c;
+ wi->scene_global = global;
+ }
+}
+
+#endif
--- /dev/null
+//This software module was originally developed by TelecomParisTech in the
+//course of the development of MPEG-U Widgets (ISO/IEC 23007-1) standard.
+//
+//This software module is an implementation of a part of one or
+//more MPEG-U Widgets (ISO/IEC 23007-1) tools as specified by the MPEG-U Widgets
+//(ISO/IEC 23007-1) standard. ISO/IEC gives users of the MPEG-U Widgets
+//(ISO/IEC 23007-1) free license to this software module or modifications
+//thereof for use in hardware or software products claiming conformance to
+//the MPEG-U Widgets (ISO/IEC 23007-1). Those intending to use this software
+//module in hardware or software products are advised that its use may
+//infringe existing patents.
+//The original developer of this software module and his/her company, the
+//subsequent editors and their companies, and ISO/IEC have no liability
+//for use of this software module or modifications thereof in an implementation.
+//Copyright is not released for non MPEG-U Widgets (ISO/IEC 23007-1) conforming
+//products.
+//Telecom ParisTech retains full right to use the code for his/her own purpose,
+//assign or donate the code to a third party and to inhibit third parties from
+//using the code for non MPEG-U Widgets (ISO/IEC 23007-1) conforming products.
+//
+//This copyright notice must be included in all copies or derivative works.
+//
+//Copyright (c) 2009.
+//
+// Alternatively, this software module may be redistributed and/or modified
+// it under the terms of the GNU Lesser General Public License as published by
+// the Free Software Foundation; either version 2, or (at your option)
+// any later version.
+//
+/////////////////////////////////////////////////////////////////////////////////
+
+
+/////////////////////////////////////////////////////////////////////////////////
+//
+// Authors:
+// Jean Le Feuvre, Telecom ParisTech
+// Cyril Concolato, Telecom ParisTech
+//
+/////////////////////////////////////////////////////////////////////////////////
+
+#include "widgetman.h"
+
+#ifdef GPAC_HAS_SPIDERMONKEY
+
+#if !defined(__GNUC__)
+# pragma comment(lib, "js32")
+#endif
+
+
+JSBool gf_sg_js_event_add_listener(JSContext *c, JSObject *obj, uintN argc, jsval *argv, jsval *rval, GF_Node *vrml_node);
+JSBool gf_sg_js_event_remove_listener(JSContext *c, JSObject *obj, uintN argc, jsval *argv, jsval *rval, GF_Node *vrml_node);
+
+
+
+static Bool is_same_path(const char *p1, const char *p2, u32 len)
+{
+ char c1, c2;
+ u32 i=0;
+ do {
+ if (len && (i==len))
+ break;
+ c1 = p1[i];
+ c2 = p2[i];
+ if (p1[i] != p2[i]) {
+ if ((c1=='/') && (c2=='\\')) {}
+ else if ((c1=='\\') && (c2=='/')) {}
+ else return 0;
+ }
+ i++;
+ } while (c1);
+ return 1;
+}
+
+static void widget_package_extract_file(GF_WidgetPackage *wpack, GF_WidgetPackageResource *res)
+{
+ u32 i, count;
+
+ if (wpack->is_zip) {
+ unz_global_info gi;
+ unzFile uf = unzOpen2(wpack->package_path, NULL);
+ if (!uf) return;
+
+ unzGetGlobalInfo(uf, &gi);
+ for (i=0; i<gi.number_entry; i++) {
+ char buf[8192];
+ int err;
+ FILE *fout;
+ char filename_inzip[256];
+
+ unz_file_info file_info;
+ unzGetCurrentFileInfo(uf, &file_info, filename_inzip,sizeof(filename_inzip),NULL,0,NULL,0);
+
+ if (strcmp(res->inner_path, filename_inzip)) {
+ if ((i+1)<gi.number_entry)
+ unzGoToNextFile(uf);
+ continue;
+ }
+
+ unzOpenCurrentFile3(uf, NULL, NULL, 0, NULL/*password*/);
+
+ fout=gf_f64_open(res->extracted_path, "wb");
+ if (!fout) break;
+ do {
+ err = unzReadCurrentFile(uf,buf,8192);
+ if (err<0) break;
+ if (err>0)
+ if (gf_fwrite(buf,err,1,fout)!=1) {
+ err=UNZ_ERRNO;
+ break;
+ }
+ } while (err>0);
+ if (fout) fclose(fout);
+
+ res->extracted = 1;
+ break;
+ }
+ unzClose(uf);
+ } else {
+ GF_ISOFile *isom = gf_isom_open(wpack->package_path, GF_ISOM_OPEN_READ, 0);
+ if (!isom ) return;
+
+ count = gf_isom_get_meta_item_count(isom, 1, 0);
+ for (i=0; i<count; i++) {
+ u32 ID;
+ const char *url, *urn, *enc;
+ Bool self_ref;
+ const char *item_name;
+
+ gf_isom_get_meta_item_info(isom, 1, 0, i+1, &ID, NULL, &self_ref, &item_name, NULL, &enc, &url, &urn);
+ if (strcmp(res->inner_path, item_name)) continue;
+
+ gf_isom_extract_meta_item(isom, 1, 0, ID, res->extracted_path);
+ res->extracted = 1;
+ break;
+ }
+ gf_isom_close(isom);
+ }
+
+}
+
+static Bool package_find_res(GF_WidgetPackage *wpack, char *res_path, char *relocated_path, char *localized_rel_path)
+{
+ u32 count, i;
+ count = gf_list_count(wpack->resources);
+ for (i=0;i<count;i++) {
+ GF_WidgetPackageResource *pack_res = gf_list_get(wpack->resources, i);
+ if (is_same_path(res_path, pack_res->inner_path, 0)) {
+ strcpy(localized_rel_path, res_path);
+ strcpy(relocated_path, pack_res->extracted_path);
+ if (!pack_res->extracted) widget_package_extract_file(wpack, pack_res);
+ return 1;
+ }
+ }
+ return 0;
+}
+
+/* Checks if a resource in the package has the given rel_path, potentially in a localized sub-folder */
+static Bool widget_package_relocate_uri(void *__self, const char *parent_uri, const char *rel_path, char *relocated_path, char *localized_rel_path)
+{
+ char path[GF_MAX_PATH];
+ const char *opt;
+ GF_WidgetPackage *wpack = (GF_WidgetPackage *)__self;
+
+ assert(parent_uri);
+ /*resource belongs to our archive*/
+ if (strstr(rel_path, wpack->archive_id)) {
+ rel_path = strstr(rel_path, wpack->archive_id) + strlen(wpack->archive_id);
+ }
+ /*parent resource belongs to our archive*/
+ else if (strstr(parent_uri, wpack->archive_id)) {
+ }
+ /*resource doesn't belong to our archive*/
+ else {
+ return 0;
+ }
+
+ /* First try to locate the resource in the locales folder */
+ opt = gf_cfg_get_key(wpack->wm->term->user->config, "Systems", "Language2CC");
+ if (opt) {
+ if (!strcmp(opt, "*") || !strcmp(opt, "un") )
+ opt = NULL;
+ }
+
+ while (opt) {
+ char lan[100];
+ char *sep;
+ char *sep_lang = strchr(opt, ';');
+ if (sep_lang) sep_lang[0] = 0;
+
+ while (strchr(" \t", opt[0]))
+ opt++;
+ strcpy(lan, opt);
+
+ if (sep_lang) {
+ sep_lang[0] = ';';
+ opt = sep_lang+1;
+ } else {
+ opt = NULL;
+ }
+
+ while (1) {
+ sep = strstr(lan, "-*");
+ if (!sep) break;
+ strncpy(sep, sep+2, strlen(sep)-2);
+ }
+
+ sprintf(path, "locales/%s/%s", lan, rel_path);
+ if (package_find_res(wpack, path, relocated_path, localized_rel_path))
+ return 1;
+
+ /*recursively remove region (sub)tags*/
+ while (1) {
+ sep = strrchr(lan, '-');
+ if (!sep) break;
+ sep[0] = 0;
+ sprintf(path, "locales/%s/%s", lan, rel_path);
+ if (package_find_res(wpack, path, relocated_path, localized_rel_path))
+ return 1;
+ }
+ }
+
+ /*no locale*/
+ if (package_find_res(wpack, (char*)rel_path, relocated_path, localized_rel_path))
+ return 1;
+
+ strcpy(localized_rel_path, "");
+ strcpy(relocated_path, "");
+ return 0;
+}
+
+static GF_WidgetPackage *widget_isom_new(GF_WidgetManager *wm, const char *path)
+{
+ GF_WidgetPackageResource *pack_res;
+ char szPath[GF_MAX_PATH];
+ const char *dir;
+ GF_WidgetPackage *wzip;
+ u32 brand = 0;
+ u32 i, count;
+ GF_ISOFile *isom = gf_isom_open(path, GF_ISOM_OPEN_READ, 0);
+ if (!isom ) return NULL;
+
+ brand = gf_isom_get_meta_type(isom, 1, 0);
+ if ((brand!=GF_4CC('m','w','g','t') ) || !gf_isom_has_meta_xml(isom, 1, 0) ) {
+ gf_isom_close(isom);
+ return NULL;
+ }
+
+ GF_SAFEALLOC(wzip, GF_WidgetPackage);
+
+ wzip->wm = wm;
+ wzip->relocate_uri = widget_package_relocate_uri;
+ wzip->resources = gf_list_new();
+ dir = gf_cfg_get_key(wm->term->user->config, "General", "CacheDirectory");
+ /* create the extracted path for the package root using:
+ the cache dir + a CRC of the file path and the instance*/
+ sprintf(wzip->root_extracted_path, "%s%08X", path, (unsigned int)((unsigned long) wzip));
+ i = gf_crc_32((char *)wzip->root_extracted_path, strlen(wzip->root_extracted_path));
+ sprintf(wzip->archive_id, "GWM_%08X_", i);
+ sprintf(wzip->root_extracted_path, "%s/%s", dir, wzip->archive_id);
+
+
+ strcpy(szPath, wzip->root_extracted_path);
+ strcat(szPath, "config.xml");
+ if (gf_isom_extract_meta_xml(isom, 1, 0, szPath, NULL) != GF_OK) {
+ gf_list_del(wzip->resources);
+ gf_free(wzip);
+ gf_isom_close(isom);
+ return NULL;
+ }
+
+ wzip->package_path = gf_strdup(path);
+
+ GF_SAFEALLOC(pack_res, GF_WidgetPackageResource);
+ pack_res->extracted_path = gf_strdup(szPath);
+ pack_res->inner_path = gf_strdup("config.xml");
+ pack_res->extracted = 1;
+ gf_list_add(wzip->resources, pack_res);
+
+
+ count = gf_isom_get_meta_item_count(isom, 1, 0);
+ for (i=0; i<count; i++) {
+ u32 ID;
+ const char *url, *urn, *enc;
+ Bool self_ref;
+ char *sep;
+ const char *item_name;
+
+ gf_isom_get_meta_item_info(isom, 1, 0, i+1, &ID, NULL, &self_ref, &item_name, NULL, &enc, &url, &urn);
+
+ sep = strrchr(item_name, '/');
+ if (!sep) sep = strrchr(item_name, '\\');
+ if (sep) {
+ sep[0] = 0;
+ sprintf(szPath, "%s_%08X_%s", wzip->root_extracted_path, gf_crc_32((char*)item_name, strlen(item_name)), sep+1);
+ sep[0] = '/';
+ } else {
+ strcpy(szPath, wzip->root_extracted_path);
+ strcat(szPath, item_name);
+ }
+ GF_SAFEALLOC(pack_res, GF_WidgetPackageResource);
+ pack_res->extracted_path = gf_strdup(szPath);
+ pack_res->inner_path = gf_strdup(item_name);
+ pack_res->extracted = 0;
+ gf_list_add(wzip->resources, pack_res);
+ }
+ gf_isom_close(isom);
+
+
+ /* register this widget package as a relocator to enable localization of resources inside this package */
+ gf_mx_p(wm->term->net_mx);
+ gf_list_add(wm->term->uri_relocators, wzip);
+ gf_mx_v(wm->term->net_mx);
+ return wzip;
+}
+
+static GF_WidgetPackage *widget_zip_new(GF_WidgetManager *wm, const char *path)
+{
+ unz_global_info gi;
+ const char *dir;
+ u32 i;
+ GF_WidgetPackage *wzip;
+ unzFile uf = unzOpen2(path, NULL);
+ if (!uf) return NULL;
+
+ GF_SAFEALLOC(wzip, GF_WidgetPackage);
+
+ wzip->wm = wm;
+ wzip->is_zip = 1;
+ wzip->relocate_uri = widget_package_relocate_uri;
+ wzip->resources = gf_list_new();
+ wzip->package_path = gf_strdup(path);
+ dir = gf_cfg_get_key(wm->term->user->config, "General", "CacheDirectory");
+ /* create the extracted path for the package root using:
+ the cache dir + a CRC of the file path and the instance*/
+ sprintf(wzip->root_extracted_path, "%s%08X", path, (unsigned int)((unsigned long) wzip));
+ i = gf_crc_32((char *)wzip->root_extracted_path, strlen(wzip->root_extracted_path));
+ sprintf(wzip->archive_id, "GWM_%08X_", i);
+ sprintf(wzip->root_extracted_path, "%s/%s", dir, wzip->archive_id);
+
+ unzGetGlobalInfo(uf, &gi);
+ for (i=0; i<gi.number_entry; i++) {
+ char szPath[GF_MAX_PATH];
+ char *sep;
+ GF_WidgetPackageResource *pack_res;
+ char filename_inzip[256];
+ unz_file_info file_info;
+ unzGetCurrentFileInfo(uf, &file_info, filename_inzip,sizeof(filename_inzip),NULL,0,NULL,0);
+
+ sep = strrchr(filename_inzip, '/');
+ if (!sep) sep = strrchr(filename_inzip, '\\');
+ if (sep) {
+ sep[0] = 0;
+ sprintf(szPath, "%s_%08X_%s", wzip->root_extracted_path, gf_crc_32(filename_inzip, strlen(filename_inzip)), sep+1);
+ sep[0] = '/';
+ } else {
+ strcpy(szPath, wzip->root_extracted_path);
+ strcat(szPath, filename_inzip);
+ }
+
+
+ if (!strcmp(filename_inzip, "config.xml")) {
+ int err;
+ char buf[8192];
+ FILE *fout;
+ unzOpenCurrentFile3(uf, NULL, NULL, 0, NULL/*password*/);
+
+ fout=gf_f64_open(szPath,"wb");
+ if (!fout) return NULL;
+
+ do {
+ err = unzReadCurrentFile(uf,buf,8192);
+ if (err<0) break;
+
+ if (err>0)
+ if (gf_fwrite(buf,err,1,fout)!=1) {
+ err=UNZ_ERRNO;
+ break;
+ }
+ } while (err>0);
+ if (fout) fclose(fout);
+ if (err==0) {
+ GF_SAFEALLOC(pack_res, GF_WidgetPackageResource);
+ pack_res->extracted_path = gf_strdup(szPath);
+ pack_res->inner_path = gf_strdup(filename_inzip);
+ pack_res->extracted = 1;
+ gf_list_add(wzip->resources, pack_res);
+ }
+ } else {
+ GF_SAFEALLOC(pack_res, GF_WidgetPackageResource);
+ pack_res->extracted_path = gf_strdup(szPath);
+ pack_res->inner_path = gf_strdup(filename_inzip);
+ pack_res->extracted = 0;
+ gf_list_add(wzip->resources, pack_res);
+ }
+
+ if ((i+1)<gi.number_entry)
+ unzGoToNextFile(uf);
+ }
+ unzClose(uf);
+
+ /* register this widget package as a relocator to enable localization of resources inside this package */
+ gf_mx_p(wm->term->net_mx);
+ gf_list_add(wm->term->uri_relocators, wzip);
+ gf_mx_v(wm->term->net_mx);
+ return wzip;
+}
+
+GF_WidgetPackage *widget_package_new(GF_WidgetManager *wm, const char *path)
+{
+ if (gf_unzip_probe(path)) {
+ return widget_zip_new(wm, path);
+ }
+ /*ISOFF-based packaged widget */
+ else if (gf_isom_probe_file(path)) {
+ return widget_isom_new(wm, path);
+ }
+ return NULL;
+}
+
+static void widget_package_del(GF_WidgetManager *wm, GF_WidgetPackage *wpackage)
+{
+ gf_mx_p(wm->term->net_mx);
+ gf_list_del_item(wm->term->uri_relocators, wpackage);
+ gf_mx_v(wm->term->net_mx);
+
+ while (gf_list_count(wpackage->resources)) {
+ GF_WidgetPackageResource *wu = gf_list_get(wpackage->resources, 0);
+ gf_list_rem(wpackage->resources, 0);
+ gf_delete_file(wu->extracted_path);
+ gf_free(wu->extracted_path);
+ gf_free(wu->inner_path);
+ gf_free(wu);
+ }
+ gf_list_del(wpackage->resources);
+ if (wpackage->sess) gf_dm_sess_del(wpackage->sess);
+ gf_free(wpackage->package_path);
+ gf_free(wpackage);
+}
+
+
+
+static void wm_delete_message_param(GF_WidgetPin *mp)
+{
+ if (!mp) return;
+ if (mp->node) gf_free(mp->node);
+ if (mp->attribute) gf_free(mp->attribute);
+ if (mp->default_value) gf_free(mp->default_value);
+ if (mp->name) gf_free(mp->name);
+ gf_free(mp);
+}
+
+static void wm_delete_widget_content(GF_WidgetContent *content)
+{
+ if (!content) return;
+
+ while (gf_list_count(content->interfaces)) {
+ GF_WidgetInterface*ifce = gf_list_last(content->interfaces);
+ gf_list_rem_last(content->interfaces);
+
+ while (gf_list_count(ifce->messages)) {
+ GF_WidgetMessage *msg = gf_list_last(ifce->messages);
+ gf_list_rem_last(ifce->messages);
+
+ while (gf_list_count(msg->params)) {
+ GF_WidgetPin *par = gf_list_last(msg->params);
+ gf_list_rem_last(msg->params);
+ wm_delete_message_param(par);
+ }
+ gf_list_del(msg->params);
+
+ wm_delete_message_param(msg->input_action);
+ wm_delete_message_param(msg->output_trigger);
+ gf_free(msg->name);
+ gf_free(msg);
+ }
+ gf_list_del(ifce->messages);
+ wm_delete_message_param(ifce->bind_action);
+ wm_delete_message_param(ifce->unbind_action);
+ if (ifce->obj) gf_js_remove_root(ifce->content->widget->wm->ctx, &ifce->obj, GF_JSGC_OBJECT);
+
+ if (ifce->connectTo) gf_free(ifce->connectTo);
+ gf_free(ifce->type);
+ gf_free(ifce);
+ }
+ gf_list_del(content->interfaces);
+
+ while (gf_list_count(content->components)) {
+ GF_WidgetComponent *comp = gf_list_last(content->components);
+ gf_list_rem_last(content->components);
+
+ wm_delete_message_param(comp->activateTrigger);
+ wm_delete_message_param(comp->deactivateTrigger);
+
+ while (gf_list_count(comp->required_interfaces)) {
+ char *type = gf_list_last(comp->required_interfaces);
+ gf_list_rem_last(comp->required_interfaces);
+ if (type) gf_free(type);
+ }
+ gf_list_del(comp->required_interfaces);
+ if (comp->id) gf_free(comp->id);
+ if (comp->src) gf_free(comp->src);
+ gf_free(comp);
+ }
+ gf_list_del(content->components);
+
+ while (gf_list_count(content->preferences)) {
+ GF_WidgetPreference *pref = gf_list_last(content->preferences);
+ gf_list_rem_last(content->preferences);
+
+ wm_delete_message_param(pref->connectTo);
+ if (pref->value) gf_free(pref->value);
+ gf_free(pref->name);
+ gf_free(pref);
+ }
+ gf_list_del(content->preferences);
+
+ wm_delete_message_param(content->saveTrigger);
+ wm_delete_message_param(content->restoreTrigger);
+ wm_delete_message_param(content->savedAction);
+ wm_delete_message_param(content->restoredAction);
+
+ gf_free(content->src);
+ gf_free(content->relocated_src);
+ gf_free(content->mimetype);
+ gf_free(content->encoding);
+ gf_free(content);
+}
+
+static void wm_delete_widget(GF_WidgetManager *wm, GF_Widget *wid)
+{
+ gf_list_del_item(wm->widgets, wid);
+
+ if (wid->url) gf_free(wid->url);
+ if (wid->manifest_path) gf_free(wid->manifest_path);
+ wm_delete_widget_content(wid->main);
+ if (wid->local_path) gf_free(wid->local_path);
+ if (wid->name) gf_free(wid->name);
+ if (wid->shortname) gf_free(wid->shortname);
+ if (wid->identifier) gf_free(wid->identifier);
+ if (wid->authorName) gf_free(wid->authorName);
+ if (wid->authorEmail) gf_free(wid->authorEmail);
+ if (wid->authorHref) gf_free(wid->authorHref);
+ if (wid->description) gf_free(wid->description);
+ if (wid->license) gf_free(wid->license);
+ if (wid->licenseHref) gf_free(wid->licenseHref);
+ if (wid->viewmodes) gf_free(wid->viewmodes);
+ if (wid->version) gf_free(wid->version);
+ if (wid->uuid) gf_free(wid->uuid);
+
+
+ while (gf_list_count(wid->icons)) {
+ GF_WidgetContent *icon = gf_list_get(wid->icons, 0);
+ gf_list_rem(wid->icons, 0);
+ wm_delete_widget_content(icon);
+ }
+ gf_list_del(wid->icons);
+
+ while (gf_list_count(wid->features)) {
+ GF_WidgetFeature *f = gf_list_get(wid->features, 0);
+ gf_list_rem(wid->features, 0);
+ if (f->name) gf_free(f->name);
+ while (gf_list_count(f->params)) {
+ GF_WidgetFeatureParam *p = gf_list_get(f->params, 0);
+ gf_list_rem(f->params, 0);
+ if (p->name) gf_free(p->name);
+ if (p->value) gf_free(p->value);
+ gf_free(p);
+ }
+ gf_free(f);
+ }
+ gf_list_del(wid->features);
+
+ if (wid->wpack) widget_package_del(wm, wid->wpack);
+ gf_free(wid);
+}
+
+static void wm_delete_interface_instance(GF_WidgetManager *wm, GF_WidgetInterfaceInstance *bifce)
+{
+ if (bifce->hostname) gf_free(bifce->hostname);
+ if (bifce->obj) {
+ JS_SetPrivate(wm->ctx, bifce->obj, NULL);
+ gf_js_remove_root(wm->ctx, &bifce->obj, GF_JSGC_OBJECT);
+ }
+ gf_free(bifce);
+}
+
+static void wm_delete_widget_instance(GF_WidgetManager *wm, GF_WidgetInstance *widg)
+{
+
+ while (gf_list_count(widg->components)) {
+ GF_WidgetComponentInstance *comp = gf_list_get(widg->components, 0);
+ gf_list_rem(widg->components, 0);
+ if (comp->wid) wm_delete_widget_instance(wm, comp->wid);
+ gf_free(comp);
+ }
+ gf_list_del(widg->components);
+
+ while (gf_list_count(widg->bound_ifces)) {
+ GF_WidgetInterfaceInstance *bifce = gf_list_get(widg->bound_ifces, 0);
+ gf_list_rem(widg->bound_ifces, 0);
+ wm_delete_interface_instance(wm, bifce);
+ }
+ gf_list_del(widg->bound_ifces);
+
+ gf_list_del(widg->output_triggers);
+
+ if (widg->obj) {
+ JS_SetPrivate(wm->ctx, widg->obj, NULL);
+ gf_js_remove_root(wm->ctx, &widg->obj, GF_JSGC_OBJECT);
+ }
+ gf_list_del_item(wm->widget_instances, widg);
+ widg->widget->nb_instances--;
+ if (!widg->widget->nb_instances) wm_delete_widget(wm, widg->widget);
+
+ if (!widg->permanent) {
+ gf_cfg_del_section(wm->term->user->config, widg->secname);
+ gf_cfg_set_key(wm->term->user->config, "Widgets", widg->secname, NULL);
+ }
+ if (widg->mpegu_context) gf_xml_dom_del(widg->mpegu_context);
+
+ gf_free(widg);
+}
+
+
+
+static JSBool wm_widget_call_script(GF_WidgetInstance *wid, GF_WidgetPin *pin, uintN argc, jsval *argv, jsval *rval)
+{
+ jsval fval;
+ if (!wid->scene_context || !wid->scene_global) return JS_FALSE;
+
+ /*if on_load property is assigned to this widget, add an event listener on the root.*/
+ JS_LookupProperty(wid->scene_context, wid->scene_global, pin->node, &fval);
+ if (JSVAL_IS_OBJECT(fval)) {
+ JS_CallFunctionValue(wid->scene_context, wid->scene_global, fval, argc, argv, rval);
+ }
+ return JS_TRUE;
+}
+
+static JSBool wm_widget_set_scene_input_value(JSContext *c, JSObject *obj, uintN argc, jsval *argv, jsval *rval, u32 type, GF_WidgetInstance *wid, GF_WidgetPin *param, const char *value)
+{
+ char *str_val;
+ GF_Node *n;
+ GF_FieldInfo info;
+ GF_WidgetMessage *msg;
+ GF_WidgetInterface *ifce;
+
+ if (!wid && obj) wid = (GF_WidgetInstance *)JS_GetPrivate(c, obj);
+ if (!wid) return JS_FALSE;
+ if (!wid->scene) return JS_TRUE;
+
+ if (!param) {
+ if (!JSVAL_IS_OBJECT(argv[0])) return JS_TRUE;
+
+ switch (type) {
+ /*set_input*/
+ case 0:
+ if (argc!=2) return JS_FALSE;
+ param = JS_GetPrivate(c, JSVAL_TO_OBJECT(argv[0]) );
+ break;
+ /*call_input_action*/
+ case 1:
+ msg = JS_GetPrivate(c, JSVAL_TO_OBJECT(argv[0]) );
+ param = msg ? msg->input_action : NULL;
+ break;
+ /*bind_interface*/
+ case 2:
+ ifce = JS_GetPrivate(c, JSVAL_TO_OBJECT(argv[0]) );
+ param = ifce ? ifce->bind_action : NULL;
+ break;
+ /*unbind_interface*/
+ case 3:
+ ifce = JS_GetPrivate(c, JSVAL_TO_OBJECT(argv[0]) );
+ param = ifce ? ifce->unbind_action : NULL;
+ break;
+ }
+ }
+
+ if (!param || !param->node) return JS_TRUE;
+ /*this is a script call*/
+ if (!param->attribute) {
+ return wm_widget_call_script(wid, param, 0, NULL, rval);
+ }
+
+ n = gf_sg_find_node_by_name(wid->scene, param->node);
+ if (!n) return JS_TRUE;
+
+ if (param->in_action) return JS_TRUE;
+
+ param->in_action = 1;
+
+#ifndef GPAC_DISABLE_SVG
+ if (n->sgprivate->tag >= GF_NODE_FIRST_DOM_NODE_TAG) {
+ u32 evt_type;
+ if (!type) {
+ char *_str_val = NULL;
+ if (value) {
+ str_val = (char *)value;
+ } else {
+ if (!JSVAL_IS_STRING(argv[1])) goto exit;
+ str_val = _str_val = SMJS_CHARS(c, argv[1]);
+ }
+
+ /* first check if the set_input refers to an attribute name or to an event name */
+ evt_type = gf_dom_event_type_by_name(param->attribute);
+
+ /*events are not allowed for <input> and <output>*/
+ if (evt_type == GF_EVENT_UNKNOWN) {
+ /* modify an attribute */
+ if (!strcmp(param->attribute, "textContent")) {
+ gf_dom_set_textContent(n, (char *)str_val);
+ gf_node_changed(n, NULL);
+ }
+ else {
+ if (gf_node_get_attribute_by_name(n, param->attribute, 0, 1, 0, &info)==GF_OK) {
+ gf_svg_parse_attribute(n, &info, (char *)str_val, 0);
+ if (info.fieldType==XMLRI_datatype) gf_node_dirty_set(n, GF_SG_SVG_XLINK_HREF_DIRTY, 0);
+ gf_node_changed(n, &info);
+ }
+ }
+ }
+ SMJS_FREE(c, _str_val);
+
+ } else {
+ GF_DOM_Event evt;
+ memset(&evt, 0, sizeof(GF_DOM_Event));
+ /* first check if the set_input refers to an attribute name or to an event name */
+ evt_type = gf_dom_event_type_by_name(param->attribute);
+ /* launch an event */
+ if (evt_type != GF_EVENT_UNKNOWN) {
+ evt.type = evt_type;
+ gf_dom_event_fire(n, &evt);
+ } else {
+ /*should we fire a DOMAttrModified event ? to clarify in the spec*/
+
+ if (gf_node_get_attribute_by_name(n, param->attribute, 0, 1, 0, &info)==GF_OK) {
+ evt.bubbles = 1;
+ evt.type = GF_EVENT_ATTR_MODIFIED;
+ evt.attr = &info;
+ gf_dom_event_fire(n, &evt);
+ }
+ }
+ }
+ } else
+#endif
+
+
+#ifndef GPAC_DISABLE_VRML
+ {
+ if (gf_node_get_field_by_name(n, param->attribute, &info) != GF_OK) return JS_TRUE;
+
+ if (!type) {
+ char *_str_val = NULL;
+ jsdouble val;
+
+ switch (info.fieldType) {
+ case GF_SG_VRML_SFSTRING:
+ if (value) {
+ str_val = (char *)value;
+ } else {
+ if (!JSVAL_IS_STRING(argv[1]))goto exit;
+ str_val = SMJS_CHARS(c, argv[1]);
+ }
+ if ( ((SFString*)info.far_ptr)->buffer) gf_free(((SFString*)info.far_ptr)->buffer);
+ ((SFString*)info.far_ptr)->buffer = str_val ? gf_strdup(str_val) : NULL;
+ break;
+ case GF_SG_VRML_SFBOOL:
+ if (value) *((SFBool*)info.far_ptr) = (!strcmp(value, "true")) ? 1 : 0;
+ else if (JSVAL_IS_BOOLEAN(argv[1])) *((SFBool*)info.far_ptr) = JSVAL_TO_BOOLEAN(argv[1]);
+ else if (JSVAL_IS_INT(argv[1])) *((SFBool*)info.far_ptr) = JSVAL_TO_INT(argv[1]);
+ else if (JSVAL_IS_STRING(argv[1])) {
+ str_val = SMJS_CHARS(c, argv[1]);
+ *((SFBool*)info.far_ptr) = (str_val && !strcmp(str_val, "true")) ? 1 : 0;
+ SMJS_FREE(c, str_val);
+ } else
+ goto exit;
+ break;
+ case GF_SG_VRML_SFINT32:
+ if (value) *((SFInt32*)info.far_ptr) = (s32) atof(value);
+ else if (JSVAL_IS_INT(argv[1])) *((SFInt32*)info.far_ptr) = JSVAL_TO_INT(argv[1]);
+ else if (JSVAL_IS_NUMBER(argv[1])) {
+ JS_ValueToNumber(c, argv[1], &val);
+ *((SFInt32*)info.far_ptr) = (s32) val;
+ } else if (JSVAL_IS_STRING(argv[1])) {
+ Double a_val;
+ str_val = SMJS_CHARS(c, argv[1]);
+ a_val = str_val ? atof(str_val) : 0;
+ *((SFInt32*)info.far_ptr) = (s32) a_val;
+ SMJS_FREE(c, str_val);
+ } else
+ goto exit;
+ break;
+ case GF_SG_VRML_SFFLOAT:
+ if (value) *((SFFloat*)info.far_ptr) = FLT2FIX(atof(value));
+ else if (JSVAL_IS_INT(argv[1])) *((SFFloat *)info.far_ptr) = INT2FIX( JSVAL_TO_INT(argv[1]) );
+ else if (JSVAL_IS_NUMBER(argv[1])) {
+ JS_ValueToNumber(c, argv[1], &val);
+ *((SFFloat *)info.far_ptr) = FLT2FIX( val );
+ } else if (JSVAL_IS_STRING(argv[1])) {
+ Double a_val;
+ str_val = SMJS_CHARS(c, argv[1]);
+ a_val = str_val ? atof(str_val) : 0;
+ *((SFFloat*)info.far_ptr) = FLT2FIX(a_val);
+ SMJS_FREE(c, str_val);
+ } else
+ goto exit;
+ break;
+ case GF_SG_VRML_SFTIME:
+ if (value) *((SFTime*)info.far_ptr) = atof(value);
+ else if (JSVAL_IS_INT(argv[1])) *((SFTime *)info.far_ptr) = JSVAL_TO_INT(argv[1]);
+ else if (JSVAL_IS_NUMBER(argv[1])) {
+ JS_ValueToNumber(c, argv[1], &val);
+ *((SFTime *)info.far_ptr) = val;
+ } else if (JSVAL_IS_STRING(argv[1])) {
+ Double a_val;
+ str_val = SMJS_CHARS(c, argv[1]);
+ a_val = str_val ? atof(str_val) : 0;
+ *((SFTime *)info.far_ptr) = a_val;
+ SMJS_FREE(c, str_val);
+ } else
+ goto exit;
+ break;
+ case GF_SG_VRML_MFSTRING:
+ if (value) {
+ str_val = (char *)value;
+ } else {
+ if (!JSVAL_IS_STRING(argv[1])) goto exit;
+ str_val = _str_val = SMJS_CHARS(c, argv[1]);
+ }
+ if ( ((GenMFField *)info.far_ptr)->count != 1) {
+ gf_sg_vrml_mf_reset(info.far_ptr, GF_SG_VRML_MFSTRING);
+ gf_sg_vrml_mf_alloc(info.far_ptr, GF_SG_VRML_MFSTRING, 1);
+ }
+ if ( ((MFString*)info.far_ptr)->vals[0]) gf_free( ((MFString*)info.far_ptr)->vals[0] );
+ ((MFString*)info.far_ptr)->vals[0] = str_val ? gf_strdup(str_val) : NULL;
+
+ SMJS_FREE(c, _str_val);
+ break;
+ }
+ }
+
+ //if this is a script eventIn call directly script
+ if ((n->sgprivate->tag==TAG_MPEG4_Script)
+#ifndef GPAC_DISABLE_X3D
+ || (n->sgprivate->tag==TAG_X3D_Script)
+#endif
+ )
+ gf_sg_script_event_in(n, &info);
+
+ gf_node_changed(n, &info);
+
+ /*if this is an exposedField, route it*/
+ if (info.eventType==GF_SG_EVENT_EXPOSED_FIELD) {
+ gf_node_event_out(n, info.fieldIndex);
+ }
+ }
+#endif /*GPAC_DISABLE_VRML*/
+
+exit:
+ param->in_action = 0;
+ return JS_TRUE;
+}
+
+
+static JSBool SMJS_FUNCTION(wm_widget_set_input)
+{
+ SMJS_OBJ
+ SMJS_ARGS
+ SMJS_DECL_RVAL
+ return wm_widget_set_scene_input_value(c, obj, argc, argv, rval, 0, NULL, NULL, NULL);
+}
+static JSBool SMJS_FUNCTION(wm_widget_call_input_action)
+{
+ SMJS_OBJ
+ SMJS_ARGS
+ SMJS_DECL_RVAL
+ return wm_widget_set_scene_input_value(c, obj, 1, argv, rval, 1, NULL, NULL, NULL);
+}
+
+
+static JSBool SMJS_FUNCTION(wm_widget_call_input_script)
+{
+ GF_WidgetMessage *msg;
+ GF_WidgetPin *param;
+ SMJS_OBJ
+ SMJS_ARGS
+ GF_WidgetInstance *wid = (GF_WidgetInstance *)JS_GetPrivate(c, obj);
+ if (!wid || (argc!=2) ) return JS_FALSE;
+ if (!wid->scene) return JS_TRUE;
+
+ if (!JSVAL_IS_OBJECT(argv[0])) return JS_TRUE;
+ msg = JS_GetPrivate(c, JSVAL_TO_OBJECT(argv[0]) );
+ param = msg ? msg->input_action : NULL;
+ if (!param || !param->node || param->attribute) return JS_FALSE;
+
+ if (JSVAL_IS_OBJECT(argv[1])) {
+ jsval *args;
+ JSObject *list = JSVAL_TO_OBJECT(argv[1]);
+ u32 i, count;
+ JS_GetArrayLength(c, list, (jsuint*) &count);
+ args = gf_malloc(sizeof(jsval)*count);
+ for (i=0; i<count; i++) {
+ JS_GetElement(c, list, (jsint) i, &args[i] );
+ }
+
+ wm_widget_call_script(wid, param, count, args, SMJS_GET_RVAL);
+
+ gf_free(args);
+ }
+ return JS_TRUE;
+}
+
+
+static void wm_handler_destroy(GF_Node *node, void *rs, Bool is_destroy)
+{
+ if (is_destroy) {
+ SVG_handlerElement *handler = (SVG_handlerElement *)node;
+ if (handler->js_fun_val) {
+ gf_js_remove_root(handler->js_context, &handler->js_fun_val, GF_JSGC_VAL);
+ handler->js_fun_val=0;
+ }
+ }
+}
+
+static SVG_handlerElement *wm_create_scene_listener(GF_WidgetInstance *wid, GF_WidgetPin *param)
+{
+ /*FIXME - we need to split SVG and base DOM !!*/
+#ifdef GPAC_DISABLE_SVG
+ return NULL;
+#else
+ u32 evt_type, att_name;
+ GF_Node *listener;
+ GF_FieldInfo info;
+ GF_Node *n = NULL;
+ SVG_handlerElement *handler;
+
+ evt_type = GF_EVENT_ATTR_MODIFIED;
+ n = gf_sg_find_node_by_name(wid->scene, param->node);
+ if (!n)
+ return NULL;
+
+ att_name = 0;
+
+#ifndef GPAC_DISABLE_SVG
+ if (n->sgprivate->tag >= GF_NODE_FIRST_DOM_NODE_TAG) {
+ /* first check if the set_input refers to an attribute name or to an event name */
+ evt_type = gf_dom_event_type_by_name(param->attribute);
+ if (evt_type == GF_EVENT_UNKNOWN) {
+ evt_type = GF_EVENT_ATTR_MODIFIED;
+
+ /* modify textContent */
+ if (!strcmp(param->attribute, "textContent")) {
+ att_name = (u32) -1;
+ }
+ /* modify an attribute */
+ else if (gf_node_get_attribute_by_name(n, param->attribute, 0, 1, 0, &info)==GF_OK) {
+ att_name = info.fieldIndex;
+ }
+ else {
+ return NULL;
+ }
+ }
+ } else
+#endif
+ {
+ if (gf_node_get_field_by_name(n, param->attribute, &info) != GF_OK)
+ return NULL;
+ att_name = info.fieldIndex;
+ }
+
+ listener = gf_node_new(wid->scene, TAG_SVG_listener);
+
+ handler = (SVG_handlerElement *) gf_node_new(wid->scene, TAG_SVG_handler);
+ /*we register the handler with the listener node to avoid modifying the DOM*/
+ gf_node_register((GF_Node *)handler, listener);
+ gf_node_list_add_child(& ((GF_ParentNode *)listener)->children, (GF_Node*)handler);
+ handler->sgprivate->UserCallback = wm_handler_destroy;
+
+ /*create attributes if needed*/
+ gf_node_get_attribute_by_tag(listener, TAG_XMLEV_ATT_event, 1, 0, &info);
+ ((XMLEV_Event*)info.far_ptr)->type = evt_type;
+ ((XMLEV_Event*)info.far_ptr)->parameter = att_name;
+ gf_node_get_attribute_by_tag(listener, TAG_XMLEV_ATT_handler, 1, 0, &info);
+ ((XMLRI*)info.far_ptr)->target = (GF_Node*)handler;
+ gf_node_get_attribute_by_tag(listener, TAG_XMLEV_ATT_target, 1, 0, &info);
+ ((XMLRI*)info.far_ptr)->target = n;
+
+ gf_node_get_attribute_by_tag((GF_Node*)handler, TAG_XMLEV_ATT_event, 1, 0, &info);
+ ((XMLEV_Event*)info.far_ptr)->type = evt_type;
+ ((XMLEV_Event*)info.far_ptr)->parameter = att_name;
+
+ gf_node_dom_listener_add((GF_Node *) n, listener);
+
+ return handler;
+#endif
+}
+
+static void wm_component_activation_event(GF_Node *hdl, GF_DOM_Event *evt, GF_Node *observer, Bool unload)
+{
+ JSObject *obj;
+ JSContext *c;
+ GF_WidgetInstance *wid;
+ GF_WidgetComponent *comp;
+ SVG_handlerElement *handler = (SVG_handlerElement *)hdl;
+
+ c = handler->js_context;
+ obj = handler->evt_listen_obj;
+ if (!c || !obj) return;
+ wid = (GF_WidgetInstance *)JS_GetPrivate(c, obj);
+ if (!wid) return;
+
+ comp = (GF_WidgetComponent *)handler->js_fun;
+ if (unload) {
+ wm_deactivate_component(c, wid, comp, NULL);
+ } else {
+ wm_activate_component(c, wid, comp, 0);
+ }
+}
+static void wm_component_activate_event(GF_Node *hdl, GF_DOM_Event *evt, GF_Node *observer)
+{
+ wm_component_activation_event(hdl, evt, observer, 0);
+}
+static void wm_component_deactivate_event(GF_Node *hdl, GF_DOM_Event *evt, GF_Node *observer)
+{
+ wm_component_activation_event(hdl, evt, observer, 1);
+}
+
+static void wm_widget_set_pref_event(GF_Node *hdl, GF_DOM_Event *evt, GF_Node *observer)
+{
+ char *att;
+ SVG_handlerElement *handler = (SVG_handlerElement *)hdl;
+ GF_WidgetInstance *wid = (GF_WidgetInstance *) handler->evt_listen_obj;
+ GF_WidgetPreference *pref = (GF_WidgetPreference *) handler->js_fun;
+
+ if (evt->type != GF_EVENT_ATTR_MODIFIED) return;
+
+ if (evt->detail == (u32) -1) {
+ att = gf_dom_flatten_textContent(evt->target);
+ } else {
+ att = gf_node_dump_attribute(evt->target, evt->attr);
+ if (!att) return;
+ }
+ gf_cfg_set_key(wid->widget->wm->term->user->config, wid->secname, pref->name, att);
+ gf_free(att);
+}
+
+static void on_widget_activated(JSContext *c, JSObject *obj)
+{
+ jsval funval, rval;
+ u32 i, count;
+ GF_XMLNode *context = NULL;
+ GF_WidgetInstance *wid = (GF_WidgetInstance *)JS_GetPrivate(c, obj);
+ if (!wid || wid->activated) return;
+
+ /*widget is now activated*/
+ wid->activated = 1;
+
+ /*for all components, setup bindings on activateTrigger & deactivateTrigger*/
+ count = gf_list_count(wid->widget->main->components);
+ for (i=0; i<count; i++) {
+ GF_WidgetComponent *comp = gf_list_get(wid->widget->main->components, i);
+ /*setup listener*/
+ if (comp->activateTrigger && comp->activateTrigger->attribute) {
+ SVG_handlerElement *a_hdl = wm_create_scene_listener(wid, comp->activateTrigger);
+ if (!a_hdl) return;
+ a_hdl->evt_listen_obj = obj;
+ a_hdl->js_context = c;
+ a_hdl->js_fun = comp;
+ a_hdl->handle_event = wm_component_activate_event;
+ }
+ /*setup listener*/
+ if (comp->deactivateTrigger && comp->deactivateTrigger->attribute) {
+ SVG_handlerElement *a_hdl = wm_create_scene_listener(wid, comp->deactivateTrigger);
+ if (!a_hdl) continue;
+ a_hdl->evt_listen_obj = obj;
+ a_hdl->js_context = c;
+ a_hdl->js_fun = comp;
+ a_hdl->handle_event = wm_component_deactivate_event;
+ }
+ }
+
+ if (wid->mpegu_context)
+ context = gf_xml_dom_get_root(wid->mpegu_context);
+
+ /*load preferences*/
+ count = gf_list_count(wid->widget->main->preferences);
+ for (i=0; i<count; i++) {
+ const char *value;
+ GF_WidgetPreference *pref = gf_list_get(wid->widget->main->preferences, i);
+
+
+ /*get stored value for this preference*/
+ value = gf_cfg_get_key(wid->widget->wm->term->user->config, wid->secname, pref->name);
+ /*if none found, use preference*/
+ if (!value) value = pref->value;
+
+ /*and overload with migrated context*/
+ if (context) {
+ GF_XMLNode *pref_node;
+ u32 j=0;
+ while ((pref_node = gf_list_enum(context->content, &j))) {
+ const char *att;
+ if (pref_node->type != GF_XML_NODE_TYPE) continue;
+ if (strcmp(pref_node->name, "preference")) continue;
+ att = wm_xml_get_attr(pref_node, "name");
+ if (!att) continue;
+ if (strcmp(att, pref->name)) continue;
+
+ att = wm_xml_get_attr(pref_node, "value");
+ if (att) value = att;
+ break;
+ }
+ }
+
+ if (pref->connectTo) {
+ SVG_handlerElement *hdl;
+
+ if (value)
+ wm_widget_set_scene_input_value(NULL, NULL, 0, 0, 0, 0, wid, pref->connectTo, value);
+
+ /*preference is read only, do not setup listener*/
+ if (pref->flags & GF_WM_PREF_READONLY) continue;
+ /*preference is migratable only, do not setup listener*/
+ if (!(pref->flags & GF_WM_PREF_SAVE)) continue;
+
+ /*create the listener*/
+ hdl = wm_create_scene_listener(wid, pref->connectTo);
+ if (!hdl) continue;
+
+ hdl->evt_listen_obj = wid;
+ hdl->js_fun = pref;
+ hdl->handle_event = wm_widget_set_pref_event;
+
+ }
+ }
+ if (count && wid->widget->main->restoredAction) {
+ wm_widget_set_scene_input_value(wid->widget->wm->ctx, wid->obj, 0, NULL, &rval, 0, wid, wid->widget->main->restoredAction, NULL);
+ }
+
+ if (wid->mpegu_context) {
+ gf_xml_dom_del(wid->mpegu_context);
+ wid->mpegu_context = NULL;
+ }
+
+ gf_sg_lock_javascript(wid->widget->wm->ctx, 1);
+ /*refresh all interface bindings*/
+ JS_LookupProperty(wid->widget->wm->ctx, wid->widget->wm->obj, "check_bindings", &funval);
+ if (JSVAL_IS_OBJECT(funval)) {
+ JS_CallFunctionValue(wid->widget->wm->ctx, wid->widget->wm->obj, funval, 0, 0, &rval);
+ }
+
+ /*if on_load property is assigned to this widget, call it.*/
+ JS_LookupProperty(c, obj, "on_load", &funval);
+ if (JSVAL_IS_OBJECT(funval)) {
+ JS_CallFunctionValue(wid->widget->wm->ctx, wid->obj, funval, 0, 0, &rval);
+ }
+ gf_sg_lock_javascript(wid->widget->wm->ctx, 0);
+}
+
+
+static void wm_widget_load_event(GF_Node *hdl, GF_DOM_Event *evt, GF_Node *observer)
+{
+ JSObject *obj;
+ JSContext *c;
+ SVG_handlerElement *handler = (SVG_handlerElement *)hdl;
+
+ c = handler->js_context;
+ obj = handler->evt_listen_obj;
+ if (!c || !obj) return;
+
+ on_widget_activated(c, obj);
+}
+
+
+static JSBool SMJS_FUNCTION(wm_widget_activate)
+{
+ SVG_handlerElement *handler;
+ GF_MediaObject *mo;
+ Bool direct_trigger = 0;
+ MFURL url;
+ SFURL _url;
+ GF_Node *inl;
+ SMJS_OBJ
+ SMJS_ARGS
+ GF_WidgetInstance *wid = (GF_WidgetInstance *)JS_GetPrivate(c, obj);
+ if (!wid || !argc) return JS_FALSE;
+
+ if (!JSVAL_IS_OBJECT(argv[0])) return JS_FALSE;
+
+ inl = gf_sg_js_get_node(c, JSVAL_TO_OBJECT(argv[0]) );
+ if (!inl) return JS_FALSE;
+
+ _url.OD_ID = 0;
+ _url.url = gf_url_concatenate(wid->widget->url, wid->widget->main->relocated_src);
+ url.count = 1;
+ url.vals = &_url;
+ mo = gf_mo_register(inl, &url, 0, 1);
+ if (mo) {
+ wid->scene = gf_mo_get_scenegraph(mo);
+ if (wid->scene && gf_sg_get_root_node(wid->scene)) direct_trigger = 1;
+ }
+ if (_url.url) gf_free(_url.url);
+
+ wid->anchor = inl;
+
+ if (direct_trigger) {
+ on_widget_activated(c, obj);
+ } else {
+#ifndef GPAC_DISABLE_SVG
+ handler = gf_dom_listener_build(inl, GF_EVENT_SCENE_ATTACHED, 0);
+ handler->handle_event = wm_widget_load_event;
+ handler->js_context = c;
+ handler->evt_listen_obj = obj;
+#endif
+ }
+
+ return JS_TRUE;
+}
+
+
+static void wm_handle_dom_event(GF_Node *hdl, GF_DOM_Event *event, GF_Node *observer)
+{
+ GF_FieldInfo info;
+ GF_Node *n;
+ jsval argv[1], rval, jsfun;
+ SVG_handlerElement *handler = (SVG_handlerElement *) hdl;
+ GF_WidgetPin *param = handler->js_fun;
+ GF_WidgetInstance *wid = (GF_WidgetInstance *)handler->evt_listen_obj;
+
+ if (!wid->scene)
+ return;
+
+ n = gf_sg_find_node_by_name(wid->scene, param->node);
+ if (!n) return;
+
+ /*this is a regular event output*/
+ if (event->type != GF_EVENT_ATTR_MODIFIED) {
+ jsfun = (jsval) handler->js_fun_val;
+ if (JSVAL_IS_OBJECT(jsfun))
+ JS_CallFunctionValue(handler->js_context, wid->obj, (jsval) handler->js_fun_val, 0, 0, &rval);
+ return;
+ }
+
+ /*otherwise this is a node.attr output through DOMAttributeModified*/
+ argv[0] = JSVAL_NULL;
+
+#ifndef GPAC_DISABLE_SVG
+ if (n->sgprivate->tag >= GF_NODE_FIRST_DOM_NODE_TAG) {
+ if (!strcmp(param->attribute, "textContent")) {
+ char *txt = gf_dom_flatten_textContent(n);
+ argv[0] = STRING_TO_JSVAL( JS_NewStringCopyZ(handler->js_context, txt ? txt : "") );
+ if (txt) gf_free(txt);
+ } else if (gf_node_get_attribute_by_name(n, param->attribute, 0, 1, 0, &info)==GF_OK) {
+ char *attValue;
+ if (event->attr->fieldIndex != info.fieldIndex) return;
+
+ attValue = gf_node_dump_attribute(n, &info);
+ argv[0] = STRING_TO_JSVAL( JS_NewStringCopyZ(handler->js_context, attValue) );
+ if (attValue) gf_free(attValue);
+ } else {
+ return;
+ }
+ } else
+#endif
+ {
+ if (gf_node_get_field_by_name(n, param->attribute, &info) != GF_OK) return;
+ if (event->attr->fieldIndex != info.fieldIndex) return;
+
+ switch (info.fieldType) {
+ case GF_SG_VRML_SFSTRING:
+ argv[0] = STRING_TO_JSVAL( JS_NewStringCopyZ(handler->js_context, ((SFString*)info.far_ptr)->buffer ) );
+ break;
+ case GF_SG_VRML_SFINT32:
+ argv[0] = INT_TO_JSVAL( *((SFInt32*)info.far_ptr) );
+ break;
+ case GF_SG_VRML_SFBOOL:
+ argv[0] = BOOLEAN_TO_JSVAL( *((SFBool*)info.far_ptr) );
+ break;
+ case GF_SG_VRML_SFFLOAT:
+ argv[0] = DOUBLE_TO_JSVAL( JS_NewDouble(handler->js_context, FIX2FLT( *((SFFloat*)info.far_ptr) ) ) );
+ break;
+ case GF_SG_VRML_SFTIME:
+ argv[0] = DOUBLE_TO_JSVAL( JS_NewDouble(handler->js_context, *((SFTime *)info.far_ptr) ) );
+ break;
+ }
+ }
+
+ jsfun = (jsval) handler->js_fun_val;
+ if (JSVAL_IS_OBJECT(jsfun))
+ JS_CallFunctionValue(handler->js_context, wid->obj, (jsval) handler->js_fun_val, 1, argv, &rval);
+}
+
+static JSBool SMJS_FUNCTION(wm_widget_get_param_value)
+{
+ GF_Node *n;
+ GF_FieldInfo info;
+ GF_WidgetPin *param;
+ SMJS_OBJ
+ SMJS_ARGS
+ GF_WidgetInstance *wid = (GF_WidgetInstance *)JS_GetPrivate(c, obj);
+ if (!wid || !wid->scene || !argc || !JSVAL_IS_OBJECT(argv[0]) ) return JS_FALSE;
+
+ param = JS_GetPrivate(c, JSVAL_TO_OBJECT(argv[0]) );
+ if (!param) return JS_FALSE;
+
+ if (!param->node) {
+ if (param->default_value) {
+ SMJS_SET_RVAL( STRING_TO_JSVAL( JS_NewStringCopyZ(c, param->default_value) ) );
+ return JS_TRUE;
+ }
+ return JS_FALSE;
+ }
+
+ n = gf_sg_find_node_by_name(wid->scene, param->node);
+ if (!n) return JS_FALSE;
+
+#ifndef GPAC_DISABLE_SVG
+ if (n->sgprivate->tag >= GF_NODE_FIRST_DOM_NODE_TAG) {
+ if (!strcmp(param->attribute, "textContent")) {
+ char *txt = gf_dom_flatten_textContent(n);
+ SMJS_SET_RVAL( STRING_TO_JSVAL( JS_NewStringCopyZ(c, txt ? txt : "") ));
+ if (txt) gf_free(txt);
+ } else if (gf_node_get_attribute_by_name(n, param->attribute, 0, 1, 0, &info)==GF_OK) {
+ char *attValue = gf_node_dump_attribute(n, &info);
+ SMJS_SET_RVAL( STRING_TO_JSVAL( JS_NewStringCopyZ(c, attValue) ));
+ if (attValue) gf_free(attValue);
+ } else {
+ return JS_FALSE;
+ }
+ } else
+#endif
+ {
+ if (gf_node_get_field_by_name(n, param->attribute, &info) != GF_OK) return JS_FALSE;
+
+ switch (info.fieldType) {
+ case GF_SG_VRML_SFSTRING:
+ SMJS_SET_RVAL( STRING_TO_JSVAL( JS_NewStringCopyZ(c, ((SFString*)info.far_ptr)->buffer ) ) );
+ break;
+ case GF_SG_VRML_SFINT32:
+ SMJS_SET_RVAL( INT_TO_JSVAL( *((SFInt32*)info.far_ptr) ));
+ break;
+ case GF_SG_VRML_SFBOOL:
+ SMJS_SET_RVAL(BOOLEAN_TO_JSVAL( *((SFBool*)info.far_ptr) ));
+ break;
+ case GF_SG_VRML_SFFLOAT:
+ SMJS_SET_RVAL( DOUBLE_TO_JSVAL( JS_NewDouble(c, FIX2FLT( *((SFFloat*)info.far_ptr) ) ) ));
+ break;
+ case GF_SG_VRML_SFTIME:
+ SMJS_SET_RVAL( DOUBLE_TO_JSVAL( JS_NewDouble(c, *((SFTime *)info.far_ptr) ) ));
+ break;
+ }
+ }
+
+ return JS_TRUE;
+}
+
+static JSBool SMJS_FUNCTION(wm_widget_get_message_param)
+{
+ GF_WidgetPin *par = NULL;
+ SMJS_OBJ
+ SMJS_ARGS
+ GF_WidgetMessage *msg = (GF_WidgetMessage *)JS_GetPrivate(c, obj);
+ if (!msg || !argc ) return JS_FALSE;
+
+ if (JSVAL_IS_INT(argv[0])) {
+ u32 idx = JSVAL_TO_INT(argv[0]);
+ par = gf_list_get(msg->params, idx);
+ } else if (JSVAL_IS_STRING(argv[0])) {
+ u32 i, count = gf_list_count(msg->params);
+ char *name = SMJS_CHARS(c, argv[0]);
+ for (i=0; i<count; i++) {
+ par = gf_list_get(msg->params, i);
+ if (!strcmp(par->name, name)) break;
+ par = NULL;
+ }
+ SMJS_FREE(c, name);
+ }
+
+ if (par) {
+ JSObject *obj = JS_NewObject(c, &msg->ifce->content->widget->wm->widgetAnyClass, 0, 0);
+ JS_SetPrivate(c, obj, par);
+ JS_DefineProperty(c, obj, "name", STRING_TO_JSVAL( JS_NewStringCopyZ(c, par->name) ), 0, 0, JSPROP_READONLY | JSPROP_PERMANENT);
+ JS_DefineProperty(c, obj, "is_input", BOOLEAN_TO_JSVAL( (par->type == GF_WM_PARAM_OUTPUT) ? JS_FALSE : JS_TRUE), 0, 0, JSPROP_READONLY | JSPROP_PERMANENT);
+ switch (par->script_type) {
+ case GF_WM_PARAM_SCRIPT_BOOL:
+ JS_DefineProperty(c, obj, "script_type", STRING_TO_JSVAL( JS_NewStringCopyZ(c, "boolean") ), 0, 0, JSPROP_READONLY | JSPROP_PERMANENT);
+ break;
+ case GF_WM_PARAM_SCRIPT_NUMBER:
+ JS_DefineProperty(c, obj, "script_type", STRING_TO_JSVAL( JS_NewStringCopyZ(c, "number") ), 0, 0, JSPROP_READONLY | JSPROP_PERMANENT);
+ break;
+ case GF_WM_PARAM_SCRIPT_STRING:
+ default:
+ JS_DefineProperty(c, obj, "script_type", STRING_TO_JSVAL( JS_NewStringCopyZ(c, "string") ), 0, 0, JSPROP_READONLY | JSPROP_PERMANENT);
+ break;
+ }
+ SMJS_SET_RVAL( OBJECT_TO_JSVAL(obj) );
+ }
+ return JS_TRUE;
+}
+
+static JSBool SMJS_FUNCTION(wm_widget_get_message)
+{
+ GF_WidgetMessage *msg;
+ SMJS_OBJ
+ SMJS_ARGS
+ GF_WidgetInterface *ifce = (GF_WidgetInterface*)JS_GetPrivate(c, obj);
+ if (!ifce || !argc) return JS_FALSE;
+ msg = NULL;
+
+ if (JSVAL_IS_INT(argv[0])) {
+ u32 idx;
+ idx = JSVAL_TO_INT(argv[0]);
+ msg = gf_list_get(ifce->messages, idx);
+ } else if (JSVAL_IS_STRING(argv[0])) {
+ u32 i, count = gf_list_count(ifce->messages);
+ char *name = SMJS_CHARS(c, argv[0]);
+ for (i=0; i<count; i++) {
+ msg = gf_list_get(ifce->messages, i);
+ if (!strcmp(msg->name, name)) break;
+ msg = NULL;
+ }
+ SMJS_FREE(c, name);
+ }
+ if (msg) {
+ JSObject *obj = JS_NewObject(c, &ifce->content->widget->wm->widgetAnyClass, 0, 0);
+ JS_SetPrivate(c, obj, msg);
+ JS_DefineProperty(c, obj, "num_params", INT_TO_JSVAL( gf_list_count(msg->params) ), 0, 0, JSPROP_READONLY | JSPROP_PERMANENT);
+ JS_DefineProperty(c, obj, "name", STRING_TO_JSVAL( JS_NewStringCopyZ(c, msg->name) ), 0, 0, JSPROP_READONLY | JSPROP_PERMANENT);
+ JS_DefineProperty(c, obj, "is_input", BOOLEAN_TO_JSVAL( msg->is_output ? JS_FALSE : JS_TRUE ) , 0, 0, JSPROP_READONLY | JSPROP_PERMANENT);
+ JS_DefineProperty(c, obj, "has_output_trigger", BOOLEAN_TO_JSVAL( msg->output_trigger ? JS_TRUE : JS_FALSE) , 0, 0, JSPROP_READONLY | JSPROP_PERMANENT);
+ JS_DefineProperty(c, obj, "has_input_action", BOOLEAN_TO_JSVAL( (msg->input_action && msg->input_action->attribute) ? JS_TRUE : JS_FALSE) , 0, 0, JSPROP_READONLY | JSPROP_PERMANENT);
+ JS_DefineProperty(c, obj, "has_script_input", BOOLEAN_TO_JSVAL( (msg->input_action && !msg->input_action->attribute) ? JS_TRUE : JS_FALSE) , 0, 0, JSPROP_READONLY | JSPROP_PERMANENT);
+ JS_DefineFunction(c, obj, "get_param", wm_widget_get_message_param, 1, 0);
+
+ SMJS_SET_RVAL( OBJECT_TO_JSVAL(obj) );
+ }
+ return JS_TRUE;
+}
+
+static JSBool SMJS_FUNCTION(wm_widget_get_component)
+{
+ char *comp_id;
+ u32 i, count;
+ GF_WidgetComponentInstance *comp_inst;
+ SMJS_OBJ
+ SMJS_ARGS
+ GF_WidgetInstance *wid = (GF_WidgetInstance *)JS_GetPrivate(c, obj);
+ if (!wid || !argc || !JSVAL_IS_STRING(argv[0]) ) return JS_FALSE;
+
+ comp_id = SMJS_CHARS(c, argv[0]);
+ count = gf_list_count(wid->components);
+ for (i=0; i<count;i++) {
+ comp_inst = gf_list_get(wid->components, i);
+ if (comp_inst->comp->id && !strcmp(comp_inst->comp->id, comp_id)) {
+ SMJS_SET_RVAL( OBJECT_TO_JSVAL(comp_inst->wid->obj) );
+ SMJS_FREE(c, comp_id);
+ return JS_TRUE;
+ }
+ }
+ /*if requested load the component*/
+ if ((argc==2) && JSVAL_IS_BOOLEAN(argv[1]) && (JSVAL_TO_BOOLEAN(argv[1])==JS_TRUE) ) {
+ count = gf_list_count(wid->widget->main->components);
+ for (i=0; i<count; i++) {
+ GF_WidgetComponent *comp = gf_list_get(wid->widget->main->components, i);
+ if (!comp->id || strcmp(comp->id, comp_id)) continue;
+
+ comp_inst = wm_activate_component(c, wid, comp, 1);
+ if (comp_inst) {
+ SMJS_SET_RVAL( OBJECT_TO_JSVAL(comp_inst->wid->obj) );
+ SMJS_FREE(c, comp_id);
+ return JS_TRUE;
+ }
+ SMJS_FREE(c, comp_id);
+ return JS_TRUE;
+ }
+ }
+
+ SMJS_FREE(c, comp_id);
+ return JS_TRUE;
+}
+
+static JSBool SMJS_FUNCTION(wm_widget_get_interface)
+{
+ u32 idx;
+ GF_WidgetInterface *ifce;
+ SMJS_OBJ
+ SMJS_ARGS
+ GF_WidgetInstance *wid = (GF_WidgetInstance *)JS_GetPrivate(c, obj);
+ if (!wid || !argc || !JSVAL_IS_INT(argv[0]) ) return JS_FALSE;
+
+ idx = JSVAL_TO_INT(argv[0]);
+ ifce = gf_list_get(wid->widget->main->interfaces, idx);
+
+ if (ifce) {
+ if (!ifce->obj) {
+ ifce->obj = JS_NewObject(c, &wid->widget->wm->widgetAnyClass, 0, 0);
+ JS_SetPrivate(c, ifce->obj, ifce);
+ JS_DefineProperty(c, ifce->obj, "num_messages", INT_TO_JSVAL( gf_list_count(ifce->messages) ), 0, 0, JSPROP_READONLY | JSPROP_PERMANENT);
+ JS_DefineProperty(c, ifce->obj, "type", STRING_TO_JSVAL( JS_NewStringCopyZ(c, ifce->type) ), 0, 0, JSPROP_READONLY | JSPROP_PERMANENT);
+ JS_DefineProperty(c, ifce->obj, "serviceProvider", BOOLEAN_TO_JSVAL( ifce->provider ? JS_TRUE : JS_FALSE ), 0, 0, JSPROP_READONLY | JSPROP_PERMANENT);
+ JS_DefineProperty(c, ifce->obj, "multipleBinding", BOOLEAN_TO_JSVAL( ifce->multiple_binding ? JS_TRUE : JS_FALSE ), 0, 0, JSPROP_READONLY | JSPROP_PERMANENT);
+ JS_DefineFunction(c, ifce->obj, "get_message", wm_widget_get_message, 1, 0);
+ gf_js_add_root(c, &ifce->obj, GF_JSGC_OBJECT);
+ }
+ SMJS_SET_RVAL( OBJECT_TO_JSVAL(ifce->obj) );
+ }
+ return JS_TRUE;
+}
+
+static JSBool SMJS_FUNCTION(wm_widget_bind_output_trigger)
+{
+ GF_WidgetMessage *msg;
+ GF_WidgetPin *param;
+ SVG_handlerElement *handler;
+ SMJS_OBJ
+ SMJS_ARGS
+ GF_WidgetInstance *wid = (GF_WidgetInstance *)JS_GetPrivate(c, obj);
+
+ SMJS_SET_RVAL( BOOLEAN_TO_JSVAL(JS_FALSE) );
+ if (!wid || !wid->scene || (argc!=3)) return JS_TRUE;
+
+ if (!JSVAL_IS_OBJECT(argv[0])) return JS_TRUE;
+ if (!JSVAL_IS_OBJECT(argv[1])) return JS_TRUE;
+ if (!JSVAL_IS_OBJECT(argv[2])) return JS_TRUE;
+
+ msg = (GF_WidgetMessage *)JS_GetPrivate(c, JSVAL_TO_OBJECT(argv[0]));
+ if (!msg) return JS_TRUE;
+ param = msg->output_trigger;
+ if (!param) return JS_TRUE;
+
+
+ handler = wm_create_scene_listener(wid, param);
+ if (!handler) return JS_TRUE;
+ handler->js_fun_val = * (u64 *) & argv[1];
+ gf_js_add_root(c, &handler->js_fun_val, GF_JSGC_VAL);
+ handler->evt_listen_obj = wid;
+ handler->js_fun = param;
+ handler->js_context = c;
+ handler->handle_event = wm_handle_dom_event;
+ handler->sgprivate->UserPrivate = JSVAL_TO_OBJECT(argv[2]);
+
+ gf_list_add(wid->output_triggers, handler);
+ SMJS_SET_RVAL( BOOLEAN_TO_JSVAL(JS_TRUE) );
+
+ return JS_TRUE;
+}
+
+static JSBool SMJS_FUNCTION(wm_widget_get_context)
+{
+ GF_BitStream *bs;
+ u32 i, count;
+ const char *str;
+ char *att;
+ SMJS_OBJ
+ //SMJS_ARGS
+ GF_WidgetInstance *wid = (GF_WidgetInstance *)JS_GetPrivate(c, obj);
+ if (!wid) return JS_FALSE;
+ if (!wid->scene) {
+ SMJS_SET_RVAL(JSVAL_NULL);
+ return JS_TRUE;
+ }
+
+ bs = gf_bs_new(NULL, 0, GF_BITSTREAM_WRITE);
+ str = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<contextInformation xmlns=\"urn:mpeg:mpegu:schema:widgets:contextinfo:2010\">\n";
+ gf_bs_write_data(bs, (u8 *) str, strlen(str) );
+
+ count = gf_list_count(wid->widget->main->preferences);
+ for (i=0; i<count; i++) {
+ GF_WidgetPreference *pref = gf_list_get(wid->widget->main->preferences, i);
+
+ /*preference is read only, do not include in context*/
+ if (pref->flags & GF_WM_PREF_READONLY) continue;
+ /*preference is not migratable, do not include in context*/
+ if (!(pref->flags & GF_WM_PREF_MIGRATE)) continue;
+
+ str = " <preference name=\"";
+ gf_bs_write_data(bs, (u8 *) str, strlen(str) );
+
+ gf_bs_write_data(bs, (u8 *) pref->name, strlen(pref->name) );
+
+ str = "\" value=\"";
+ gf_bs_write_data(bs, (u8 *) str, strlen(str) );
+
+ /*read from node*/
+ if (pref->connectTo && pref->connectTo->attribute) {
+ GF_FieldInfo info;
+ GF_Node *n = gf_sg_find_node_by_name(wid->scene, pref->connectTo->node);
+ if (n) {
+
+#ifndef GPAC_DISABLE_SVG
+ if ((n->sgprivate->tag >= GF_NODE_FIRST_DOM_NODE_TAG) && !strcmp(pref->connectTo->attribute, "textContent")) {
+ char *txt = gf_dom_flatten_textContent(n);
+ gf_bs_write_data(bs, (u8 *) txt, strlen(txt) );
+ } else
+#endif
+ if (gf_node_get_field_by_name(n, pref->connectTo->attribute, &info)==GF_OK) {
+ att = gf_node_dump_attribute(n, &info);
+ if (att) {
+ gf_bs_write_data(bs, (u8 *) att, strlen(att) );
+ gf_free(att);
+ }
+ }
+ }
+ }
+ /*read from config*/
+ else {
+ att = (char *)gf_cfg_get_key(wid->widget->wm->term->user->config, wid->secname, pref->name);
+ if (!att) att = pref->value;
+
+ if (att) gf_bs_write_data(bs, (u8 *) att, strlen(att) );
+ }
+
+ str = "\"/>\n";
+ gf_bs_write_data(bs, (u8 *) str, strlen(str) );
+ }
+ str = "</contextInformation>\n";
+ gf_bs_write_data(bs, (u8 *) str, strlen(str) );
+
+ gf_bs_write_u8(bs, 0);
+ att = NULL;
+ gf_bs_get_content(bs, &att, &count);
+ gf_bs_del(bs);
+
+ SMJS_SET_RVAL( STRING_TO_JSVAL( JS_NewStringCopyZ(c, att) ) );
+ gf_free(att);
+
+ return JS_TRUE;
+}
+
+
+static JSBool wm_widget_getProperty(JSContext *c, JSObject *obj, SMJS_PROP_GETTER, jsval *vp)
+{
+ JSString *s;
+ char *prop_name;
+ const char *opt;
+ GF_WidgetInstance *wid = (GF_WidgetInstance *)JS_GetPrivate(c, obj);
+ if (!wid) return JS_FALSE;
+
+ if (!SMJS_ID_IS_STRING(id)) return JS_TRUE;
+ prop_name = SMJS_CHARS_FROM_STRING(c, SMJS_ID_TO_STRING(id));
+ if (!prop_name) return JS_FALSE;
+
+ /*
+ Manifest properties
+ */
+ if (!strcmp(prop_name, "manifest")) {
+ s = JS_NewStringCopyZ(c, wid->widget->manifest_path);
+ *vp = STRING_TO_JSVAL(s);
+ }
+ else if (!strcmp(prop_name, "url")) {
+ s = JS_NewStringCopyZ(c, wid->widget->local_path ? wid->widget->local_path : wid->widget->url);
+ *vp = STRING_TO_JSVAL(s);
+ }
+ else if (!strcmp(prop_name, "main")) {
+ s = JS_NewStringCopyZ(c, wid->widget->main->relocated_src);
+ *vp = STRING_TO_JSVAL(s);
+ }
+ else if (!strcmp(prop_name, "localizedSrc")) {
+ s = JS_NewStringCopyZ(c, wid->widget->main->src);
+ *vp = STRING_TO_JSVAL(s);
+ }
+ else if (!strcmp(prop_name, "mainEncoding")) {
+ s = JS_NewStringCopyZ(c, wid->widget->main->encoding);
+ *vp = STRING_TO_JSVAL(s);
+ }
+ else if (!strcmp(prop_name, "mainMimeType")) {
+ s = JS_NewStringCopyZ(c, wid->widget->main->mimetype);
+ *vp = STRING_TO_JSVAL(s);
+ }
+ else if (!strcmp(prop_name, "defaultWidth")) {
+ *vp = INT_TO_JSVAL(wid->widget->width);
+ }
+ else if (!strcmp(prop_name, "defaultHeight")) {
+ *vp = INT_TO_JSVAL(wid->widget->height);
+ }
+ else if (!strcmp(prop_name, "icons")) {
+ u32 i, count;
+ JSObject *arr;
+ count = gf_list_count(wid->widget->icons);
+ arr = JS_NewArrayObject(c, count, NULL);
+ for (i = 0; i<count; i++) {
+ GF_WidgetContent *icon = gf_list_get(wid->widget->icons, i);
+ if (icon) {
+ char *abs_reloc_url;
+ jsval icon_obj_val;
+ JSObject *icon_obj = JS_NewObject(c, &wid->widget->wm->widgetAnyClass, 0, 0);
+ JS_SetPrivate(c, icon_obj, icon);
+ JS_DefineProperty(c, icon_obj, "src", STRING_TO_JSVAL( JS_NewStringCopyZ(c, icon->src) ), 0, 0, JSPROP_READONLY | JSPROP_PERMANENT);
+ if (strlen(icon->relocated_src)) abs_reloc_url = gf_url_concatenate(wid->widget->url, icon->relocated_src);
+ else abs_reloc_url = gf_strdup("");
+ JS_DefineProperty(c, icon_obj, "relocated_src", STRING_TO_JSVAL( JS_NewStringCopyZ(c, abs_reloc_url) ), 0, 0, JSPROP_READONLY | JSPROP_PERMANENT);
+ JS_DefineProperty(c, icon_obj, "width", INT_TO_JSVAL( icon->width ), 0, 0, JSPROP_READONLY | JSPROP_PERMANENT);
+ JS_DefineProperty(c, icon_obj, "height", INT_TO_JSVAL( icon->height ), 0, 0, JSPROP_READONLY | JSPROP_PERMANENT);
+ icon_obj_val = OBJECT_TO_JSVAL(icon_obj);
+ JS_SetElement(c, arr, i, &icon_obj_val);
+ gf_free(abs_reloc_url);
+ }
+ }
+ *vp = OBJECT_TO_JSVAL(arr);
+ }
+ else if (!strcmp(prop_name, "preferences")) {
+ u32 i, count;
+ JSObject *arr;
+ count = gf_list_count(wid->widget->main->preferences);
+ arr = JS_NewArrayObject(c, count, NULL);
+ for (i = 0; i<count; i++) {
+ GF_WidgetPreference *pref = gf_list_get(wid->widget->main->preferences, i);
+ if (pref) {
+ jsval pref_obj_val;
+ JSObject *pref_obj = JS_NewObject(c, &wid->widget->wm->widgetAnyClass, 0, 0);
+ JS_SetPrivate(c, pref_obj, pref);
+ JS_DefineProperty(c, pref_obj, "name", STRING_TO_JSVAL( JS_NewStringCopyZ(c, pref->name) ), 0, 0, JSPROP_READONLY | JSPROP_PERMANENT);
+ JS_DefineProperty(c, pref_obj, "value", STRING_TO_JSVAL( JS_NewStringCopyZ(c, pref->value) ), 0, 0, JSPROP_READONLY | JSPROP_PERMANENT);
+ JS_DefineProperty(c, pref_obj, "readonly", STRING_TO_JSVAL( JS_NewStringCopyZ(c, ((pref->flags & GF_WM_PREF_READONLY)?"true":"false")) ), 0, 0, JSPROP_READONLY | JSPROP_PERMANENT);
+ pref_obj_val = OBJECT_TO_JSVAL(pref_obj);
+ JS_SetElement(c, arr, i, &pref_obj_val);
+ }
+ }
+ *vp = OBJECT_TO_JSVAL(arr);
+ }
+ else if (!strcmp(prop_name, "features")) {
+ u32 i, count;
+ JSObject *arr;
+ count = gf_list_count(wid->widget->features);
+ arr = JS_NewArrayObject(c, count, NULL);
+ for (i = 0; i<count; i++) {
+ GF_WidgetFeature *feat = gf_list_get(wid->widget->features, i);
+ if (feat) {
+ jsval feat_obj_val;
+ JSObject *feat_obj = JS_NewObject(c, &wid->widget->wm->widgetAnyClass, 0, 0);
+ JS_SetPrivate(c, feat_obj, feat);
+ JS_DefineProperty(c, feat_obj, "name", STRING_TO_JSVAL( JS_NewStringCopyZ(c, feat->name) ), 0, 0, JSPROP_READONLY | JSPROP_PERMANENT);
+ JS_DefineProperty(c, feat_obj, "required", BOOLEAN_TO_JSVAL( (feat->required? JS_TRUE : JS_FALSE) ), 0, 0, JSPROP_READONLY | JSPROP_PERMANENT);
+ {
+ u32 j, pcount;
+ JSObject *params_arr;
+ pcount = gf_list_count(feat->params);
+ params_arr = JS_NewArrayObject(c, pcount, NULL);
+ for (j=0; j < pcount; j++) {
+ GF_WidgetFeatureParam *param = gf_list_get(feat->params, j);
+ JSObject *param_obj = JS_NewObject(c, &wid->widget->wm->widgetAnyClass, 0, 0);
+ jsval param_obj_val;
+ JS_SetPrivate(c, param_obj, param);
+ JS_DefineProperty(c, param_obj, "name", STRING_TO_JSVAL( JS_NewStringCopyZ(c, param->name) ), 0, 0, JSPROP_READONLY | JSPROP_PERMANENT);
+ JS_DefineProperty(c, param_obj, "value", STRING_TO_JSVAL( JS_NewStringCopyZ(c, param->value) ), 0, 0, JSPROP_READONLY | JSPROP_PERMANENT);
+ param_obj_val = OBJECT_TO_JSVAL(param_obj);
+ JS_SetElement(c, params_arr, j, ¶m_obj_val);
+ }
+ JS_DefineProperty(c, feat_obj, "params", OBJECT_TO_JSVAL(params_arr), 0, 0, JSPROP_READONLY | JSPROP_PERMANENT);
+ }
+ feat_obj_val = OBJECT_TO_JSVAL(feat_obj);
+ JS_SetElement(c, arr, i, &feat_obj_val);
+ }
+ }
+ *vp = OBJECT_TO_JSVAL(arr);
+ }
+
+ else if (!strcmp(prop_name, "components")) {
+ u32 i, count;
+ jsval val;
+ JSObject *arr;
+ count = gf_list_count(wid->components);
+ arr = JS_NewArrayObject(c, count, NULL);
+ for (i = 0; i<count; i++) {
+ GF_WidgetComponentInstance *comp = gf_list_get(wid->components, i);
+ val = OBJECT_TO_JSVAL(comp->wid->obj);
+ JS_SetElement(c, arr, i, &val);
+ }
+ *vp = OBJECT_TO_JSVAL(arr);
+ }
+ else if (!strcmp(prop_name, "identifier")) {
+ s = JS_NewStringCopyZ(c, wid->widget->identifier);
+ *vp = STRING_TO_JSVAL(s);
+ }
+ else if (!strcmp(prop_name, "name")) {
+ s = JS_NewStringCopyZ(c, wid->widget->name);
+ *vp = STRING_TO_JSVAL(s);
+ }
+ else if (!strcmp(prop_name, "shortName")) {
+ s = JS_NewStringCopyZ(c, wid->widget->shortname);
+ *vp = STRING_TO_JSVAL(s);
+ }
+ else if (!strcmp(prop_name, "authorName")) {
+ s = JS_NewStringCopyZ(c, wid->widget->authorName);
+ *vp = STRING_TO_JSVAL(s);
+ }
+ else if (!strcmp(prop_name, "authorEmail")) {
+ s = JS_NewStringCopyZ(c, wid->widget->authorEmail);
+ *vp = STRING_TO_JSVAL(s);
+ }
+ else if (!strcmp(prop_name, "authorHref")) {
+ s = JS_NewStringCopyZ(c, wid->widget->authorHref);
+ *vp = STRING_TO_JSVAL(s);
+ }
+ else if (!strcmp(prop_name, "description")) {
+ s = JS_NewStringCopyZ(c, wid->widget->description);
+ *vp = STRING_TO_JSVAL(s);
+ }
+ else if (!strcmp(prop_name, "viewmodes")) {
+ if (wid->widget->viewmodes) s = JS_NewStringCopyZ(c, wid->widget->viewmodes);
+ else s = JS_NewStringCopyZ(c, "");
+ *vp = STRING_TO_JSVAL(s);
+ }
+ else if (!strcmp(prop_name, "license")) {
+ s = JS_NewStringCopyZ(c, wid->widget->license);
+ *vp = STRING_TO_JSVAL(s);
+ }
+ else if (!strcmp(prop_name, "licenseHref")) {
+ s = JS_NewStringCopyZ(c, wid->widget->licenseHref);
+ *vp = STRING_TO_JSVAL(s);
+ }
+ else if (!strcmp(prop_name, "version")) {
+ s = JS_NewStringCopyZ(c, wid->widget->version);
+ *vp = STRING_TO_JSVAL(s);
+ }
+ else if (!strcmp(prop_name, "uuid")) {
+ s = JS_NewStringCopyZ(c, wid->widget->uuid);
+ *vp = STRING_TO_JSVAL(s);
+ }
+ else if (!strcmp(prop_name, "discardable")) {
+ *vp = BOOLEAN_TO_JSVAL( wid->widget->discardable ? JS_TRUE : JS_FALSE);
+ }
+ else if (!strcmp(prop_name, "multipleInstances")) {
+ *vp = BOOLEAN_TO_JSVAL( wid->widget->multipleInstance ? JS_TRUE : JS_FALSE);
+ }
+
+ /*
+ Widget Manager special properties (common to all implementations)
+ */
+ else if (!strcmp(prop_name, "permanent")) {
+ *vp = BOOLEAN_TO_JSVAL( wid->permanent ? JS_TRUE : JS_FALSE);
+ }
+ else if (!strcmp(prop_name, "is_component")) {
+ *vp = BOOLEAN_TO_JSVAL( wid->parent ? JS_TRUE : JS_FALSE);
+ }
+ else if (!strcmp(prop_name, "parent")) {
+ *vp = wid->parent ? OBJECT_TO_JSVAL(wid->parent->obj) : JSVAL_NULL;
+ }
+ else if (!strcmp(prop_name, "activated")) {
+ *vp = BOOLEAN_TO_JSVAL( wid->activated ? JS_TRUE : JS_FALSE);
+ }
+ else if (!strcmp(prop_name, "section")) {
+ s = JS_NewStringCopyZ(c, wid->secname);
+ *vp = STRING_TO_JSVAL(s);
+ }
+ else if (!strcmp(prop_name, "num_instances")) {
+ *vp = INT_TO_JSVAL( wid->widget->nb_instances);
+ }
+ else if (!strcmp(prop_name, "num_interfaces")) {
+ *vp = INT_TO_JSVAL( gf_list_count(wid->widget->main->interfaces));
+ }
+ else if (!strcmp(prop_name, "num_components")) {
+ *vp = INT_TO_JSVAL( gf_list_count(wid->components));
+ }
+ else if (!strcmp(prop_name, "num_bound_interfaces")) {
+ *vp = INT_TO_JSVAL( gf_list_count(wid->bound_ifces));
+ }
+ /*all variables used by the WidgetManager script but not stored*/
+ else if (!strcmp(prop_name, "originating_device_ip")
+ || !strcmp(prop_name, "originating_device")
+ || !strcmp(prop_name, "device")
+ ) {
+ }
+ /*
+ Widget properties, common to each implementation
+ */
+ else {
+ char szName[1024];
+ sprintf(szName, "WM:%s", prop_name);
+ opt = gf_cfg_get_key(wid->widget->wm->term->user->config, wid->secname, szName);
+ if (opt) {
+ Double val=0;
+ if (!strcmp(opt, "true")) *vp = BOOLEAN_TO_JSVAL(JS_TRUE);
+ else if (!strcmp(opt, "false")) *vp = BOOLEAN_TO_JSVAL(JS_FALSE);
+ else if (sscanf(opt, "%lf", &val)==1) {
+ *vp = DOUBLE_TO_JSVAL( JS_NewDouble(c, val) );
+ } else {
+ s = JS_NewStringCopyZ(c, opt);
+ *vp = STRING_TO_JSVAL(s);
+ }
+ }
+ }
+ SMJS_FREE(c, prop_name);
+ return JS_TRUE;
+}
+static JSBool wm_widget_setProperty(JSContext *c, JSObject *obj, SMJS_PROP_SETTER, jsval *vp)
+{
+ char szVal[32];
+ jsdouble val;
+ char *prop_name;
+ GF_WidgetInstance *wid = (GF_WidgetInstance *)JS_GetPrivate(c, obj);
+ if (!wid) return JS_FALSE;
+
+ if (!SMJS_ID_IS_STRING(id)) return JS_TRUE;
+ prop_name = SMJS_CHARS_FROM_STRING(c, SMJS_ID_TO_STRING(id));
+
+ /*internal to WidgetManager, never stored*/
+ if (!strcmp(prop_name, "permanent")) {
+ wid->permanent = (JSVAL_TO_BOOLEAN(*vp)==JS_TRUE) ? 1 : 0;
+ }
+
+ /*any widget properties*/
+ else {
+ char szName[1024], *value, *_val = NULL;
+
+ if (JSVAL_IS_STRING(*vp)) {
+ value = _val = SMJS_CHARS(c, *vp);
+ if (!value) value = "";
+ }
+ else if (JSVAL_IS_BOOLEAN(*vp)) {
+ strcpy(szVal, (JSVAL_TO_BOOLEAN(*vp)==JS_TRUE) ? "true" : "false");
+ value = szVal;
+ }
+ else if (JSVAL_IS_NUMBER(*vp)) {
+ JS_ValueToNumber(c, *vp, &val);
+ sprintf(szVal, "%f", val);
+ value = szVal;
+ } else {
+ SMJS_FREE(c, prop_name);
+ return JS_TRUE;
+ }
+
+ sprintf(szName, "WM:%s", prop_name);
+ gf_cfg_set_key(wid->widget->wm->term->user->config, wid->secname, szName, value);
+ SMJS_FREE(c, _val);
+ }
+
+ SMJS_FREE(c, prop_name);
+ return JS_TRUE;
+}
+
+
+
+static JSBool wm_widget_bind_interface_ex(JSContext *c, JSObject *obj, uintN argc, jsval *argv, jsval *rval, Bool is_unbind)
+{
+ u32 i, count;
+ GF_WidgetInterfaceInstance *bifce;
+ GF_WidgetInterface *ifce;
+ GF_WidgetInstance *wid = (GF_WidgetInstance *)JS_GetPrivate(c, obj);
+ if (!wid || !wid->scene) return JS_FALSE;
+
+ ifce = NULL;
+ if (argc) {
+ if (!JSVAL_IS_OBJECT(argv[0])) return JS_FALSE;
+ ifce = JS_GetPrivate(c, JSVAL_TO_OBJECT(argv[0]) );
+ if (!ifce) return JS_FALSE;
+ }
+
+ if (!is_unbind) {
+ char *hostname;
+ JSObject *cookie;
+ if ((argc<3) || !JSVAL_IS_OBJECT(argv[1]) || !JSVAL_IS_STRING(argv[2])) return JS_FALSE;
+
+ cookie = JSVAL_TO_OBJECT(argv[1]);
+ hostname = SMJS_CHARS(c, argv[2]);
+ count = gf_list_count(wid->bound_ifces);
+ for (i=0; i<count; i++) {
+ bifce = gf_list_get(wid->bound_ifces, i);
+ if (!strcmp(bifce->ifce->type, ifce->type) && (bifce->cookie==cookie) ) {
+ SMJS_FREE(c, hostname);
+ return JS_TRUE;
+ }
+ }
+ GF_SAFEALLOC(bifce, GF_WidgetInterfaceInstance);
+ bifce->wid = wid;
+ bifce->ifce = ifce;
+ bifce->cookie = cookie;
+ bifce->hostname = gf_strdup(hostname);
+ SMJS_FREE(c, hostname);
+ gf_list_add(wid->bound_ifces, bifce);
+
+ if (ifce->bind_action) {
+ return wm_widget_set_scene_input_value(c, obj, 1, argv, rval, 2, NULL, NULL, NULL);
+ } else {
+ widget_on_interface_bind(bifce, 0);
+ }
+ } else {
+ JSObject *cookie = NULL;
+ if ((argc==2) && JSVAL_IS_OBJECT(argv[1])) cookie = JSVAL_TO_OBJECT(argv[1]);
+
+ count = gf_list_count(wid->bound_ifces);
+ for (i=0; i<count; i++) {
+ bifce = gf_list_get(wid->bound_ifces, i);
+ if (!ifce || ( !strcmp(bifce->ifce->type, ifce->type) && (bifce->cookie==cookie)) ) {
+ gf_list_rem(wid->bound_ifces, i);
+ if (bifce->ifce->unbind_action) {
+ wm_widget_set_scene_input_value(c, NULL, 0, NULL, rval, 3, wid, bifce->ifce->unbind_action, NULL);
+ } else {
+ widget_on_interface_bind(bifce, 1);
+ }
+ if (ifce) {
+ /*unregister our message handlers*/
+ count = gf_list_count(wid->output_triggers);
+ for (i=0; i<count; i++) {
+ u32 j, c2, found;
+ GF_DOMHandler *handler = gf_list_get(wid->output_triggers, i);
+ GF_WidgetPin *param = handler->js_fun;
+
+ if (handler->sgprivate->UserPrivate != cookie) continue;
+ found = 0;
+ c2 = gf_list_count(bifce->ifce->messages);
+ for (j=0; j<c2; j++) {
+ GF_WidgetMessage *msg = gf_list_get(bifce->ifce->messages, j);
+ if (msg->output_trigger == param) {
+ found = 1;
+ break;
+ }
+ }
+ if (found) {
+ GF_Node *listener = handler->sgprivate->parents->node;
+ gf_dom_listener_del(listener, listener->sgprivate->UserPrivate);
+ gf_list_rem(wid->output_triggers, i);
+ i--;
+ count--;
+ }
+ }
+ }
+ wm_delete_interface_instance(wid->widget->wm, bifce);
+ if (ifce) return JS_TRUE;
+ i--;
+ count--;
+ }
+ }
+ }
+ return JS_TRUE;
+}
+
+static JSBool SMJS_FUNCTION(wm_widget_bind_interface)
+{
+ SMJS_OBJ
+ SMJS_ARGS
+ SMJS_DECL_RVAL
+ return wm_widget_bind_interface_ex(c, obj, argc, argv, rval, 0);
+}
+static JSBool SMJS_FUNCTION(wm_widget_unbind_interface)
+{
+ SMJS_OBJ
+ SMJS_ARGS
+ SMJS_DECL_RVAL
+ return wm_widget_bind_interface_ex(c, obj, argc, argv, rval, 1);
+}
+
+
+static JSBool SMJS_FUNCTION(wm_widget_deactivate)
+{
+ u32 i, count;
+ jsval funval;
+ SMJS_OBJ
+ GF_WidgetInstance *wid = (GF_WidgetInstance *)JS_GetPrivate(c, obj);
+ if (!wid) return JS_FALSE;
+
+ /*widget is a component of another widget, unregister*/
+ if (wid->parent) {
+ GF_WidgetInstance *par_wid = wid->parent;
+ count = gf_list_count(par_wid->components);
+ for (i=0; i<count; i++) {
+ GF_WidgetComponentInstance *comp = gf_list_get(par_wid->components, i);
+ if (comp->wid == wid) {
+ gf_list_rem(par_wid->components, i);
+ gf_free(comp);
+ break;
+ }
+ }
+ wid->parent = NULL;
+ }
+
+ /*remove all components*/
+ while (gf_list_count(wid->components)) {
+ GF_WidgetComponentInstance *comp = gf_list_get(wid->components, 0);
+ wm_deactivate_component(c, wid, NULL, comp);
+ gf_list_rem(wid->components, 0);
+ }
+
+ /*mark the widget as deactivated, so it is no longer valid when checking all widgets bindings*/
+ wid->activated = 0;
+
+ /*unbind existing widgets*/
+ JS_LookupProperty(wid->widget->wm->ctx, wid->widget->wm->obj, "unbind_widget", &funval);
+ if (JSVAL_IS_OBJECT(funval)) {
+ jsval an_argv[1];
+ an_argv[0] = OBJECT_TO_JSVAL(obj);
+ JS_CallFunctionValue(wid->widget->wm->ctx, wid->widget->wm->obj, funval, 1, an_argv, SMJS_GET_RVAL );
+ }
+
+ /*unbind all interfaces of this widget*/
+ wm_widget_bind_interface_ex(c, obj, 0, NULL, SMJS_GET_RVAL, 1);
+
+ /*detach scene now that all unbind events have been sent*/
+ wid->scene = NULL;
+ return JS_TRUE;
+}
+
+
+static void wm_widget_jsbind(GF_WidgetManager *wm, GF_WidgetInstance *wid)
+{
+ if (wid->obj)
+ return;
+ wid->obj = JS_NewObject(wm->ctx, &wm->wmWidgetClass, 0, 0);
+ JS_SetPrivate(wm->ctx, wid->obj, wid);
+ /*protect from GC*/
+ gf_js_add_root(wm->ctx, &wid->obj, GF_JSGC_OBJECT);
+}
+
+void wm_deactivate_component(JSContext *c, GF_WidgetInstance *wid, GF_WidgetComponent *comp, GF_WidgetComponentInstance *comp_inst)
+{
+ jsval fval, rval;
+
+ if (!comp_inst) {
+ u32 i=0;
+ while ((comp_inst = gf_list_enum(wid->components, &i))) {
+ if (comp_inst->comp == comp) break;
+ comp_inst = NULL;
+ }
+ }
+ if (!comp_inst) return;
+
+ if ((JS_LookupProperty(c, wid->widget->wm->obj, "on_widget_remove", &fval)==JS_TRUE) && JSVAL_IS_OBJECT(fval)) {
+ jsval argv[1];
+ argv[0] = OBJECT_TO_JSVAL(comp_inst->wid->obj);
+ JS_CallFunctionValue(wid->widget->wm->ctx, wid->obj, fval, 1, argv, &rval);
+ }
+}
+
+GF_WidgetComponentInstance *wm_activate_component(JSContext *c, GF_WidgetInstance *wid, GF_WidgetComponent *comp, Bool skip_wm_notification)
+{
+ u32 i, count;
+ const char *fun_name = NULL;
+ jsval fval, rval;
+ GF_WidgetComponentInstance *comp_inst;
+ GF_WidgetInstance *comp_wid;
+
+ comp_wid = NULL;
+ if (comp->src) {
+ char *url = gf_url_concatenate(wid->widget->url, comp->src);
+
+ count = gf_list_count(wid->widget->wm->widget_instances);
+ for (i=0; i<count; i++) {
+ comp_wid = gf_list_get(wid->widget->wm->widget_instances, i);
+ if (!strcmp(comp_wid->widget->url, url) && !comp_wid->parent) break;
+ comp_wid = NULL;
+ }
+ if (!comp_wid) {
+ comp_wid = wm_load_widget(wid->widget->wm, url, 0, 0);
+ if (comp_wid) comp_wid->permanent = 0;
+ }
+ gf_free(url);
+ }
+ if (!comp_wid) return NULL;
+
+ if (!comp_wid->activated)
+ fun_name = "on_widget_add";
+
+ GF_SAFEALLOC(comp_inst, GF_WidgetComponentInstance);
+ comp_inst->comp = comp;
+ comp_inst->wid = comp_wid;
+ comp_wid->parent = wid;
+
+ gf_list_add(wid->components, comp_inst);
+
+ if (!comp_inst->wid->obj) wm_widget_jsbind(wid->widget->wm, comp_inst->wid);
+
+ if (!skip_wm_notification && fun_name && (JS_LookupProperty(c, wid->widget->wm->obj, fun_name, &fval)==JS_TRUE) && JSVAL_IS_OBJECT(fval)) {
+ jsval argv[1];
+ argv[0] = OBJECT_TO_JSVAL(comp_inst->wid->obj);
+ JS_CallFunctionValue(wid->widget->wm->ctx, wid->obj, fval, 1, argv, &rval);
+ }
+ if (comp_inst) return comp_inst;
+ return NULL;
+}
+
+static JSBool SMJS_FUNCTION(wm_widget_is_interface_bound)
+{
+ u32 i, count;
+ JSObject *cookie;
+ GF_WidgetInterface *ifce;
+ SMJS_OBJ
+ SMJS_ARGS
+ GF_WidgetInstance *wid = (GF_WidgetInstance *)JS_GetPrivate(c, obj);
+ if (!wid || !wid->scene || (argc<1) || !JSVAL_IS_OBJECT(argv[0]) ) return JS_FALSE;
+
+ ifce = JS_GetPrivate(c, JSVAL_TO_OBJECT(argv[0]) );
+ if (!ifce) return JS_FALSE;
+ cookie = NULL;
+ if ((argc==2) && JSVAL_IS_OBJECT(argv[1]) )
+ cookie = JSVAL_TO_OBJECT(argv[1]);
+
+ SMJS_SET_RVAL(BOOLEAN_TO_JSVAL(JS_FALSE));
+ count = gf_list_count(wid->bound_ifces);
+ for (i=0; i<count; i++) {
+ GF_WidgetInterfaceInstance *bifce = gf_list_get(wid->bound_ifces, i);
+ if (!strcmp(bifce->ifce->type, ifce->type) && (!cookie || (bifce->cookie==cookie))) {
+ SMJS_SET_RVAL( BOOLEAN_TO_JSVAL(JS_TRUE) );
+ break;
+ }
+ }
+ return JS_TRUE;
+}
+
+
+static JSBool SMJS_FUNCTION(wm_load)
+{
+ u32 i, count;
+ char *manifest, *url, *widget_ctx;
+ GF_WidgetInstance *wid;
+ SMJS_OBJ
+ SMJS_ARGS
+ GF_WidgetManager *wm = (GF_WidgetManager *)JS_GetPrivate(c, obj);
+ if (!argc || !JSVAL_IS_STRING(argv[0])) return JS_TRUE;
+
+ manifest = SMJS_CHARS(c, argv[0]);
+
+ url = NULL;
+ if ((argc==2) && ! JSVAL_IS_NULL(argv[1]) && JSVAL_IS_OBJECT(argv[1])) {
+ GF_WidgetInstance *parent_widget;
+ if (!JS_InstanceOf(c, JSVAL_TO_OBJECT(argv[1]), &wm->wmWidgetClass, NULL) ) return JS_FALSE;
+ parent_widget = (GF_WidgetInstance *)JS_GetPrivate(c, JSVAL_TO_OBJECT(argv[1]) );
+
+ if (parent_widget->widget->url) url = gf_url_concatenate(parent_widget->widget->url, manifest);
+ }
+
+ widget_ctx = NULL;
+ if ((argc==3) && !JSVAL_IS_NULL(argv[2]) && JSVAL_IS_STRING(argv[2])) {
+ widget_ctx = SMJS_CHARS(c, argv[2]);
+ }
+
+ if (!url) {
+ url = gf_strdup(manifest);
+ }
+
+ wid=NULL;
+ count = gf_list_count(wm->widget_instances);
+ for (i=0; i<count; i++) {
+ wid = gf_list_get(wm->widget_instances, i);
+ if (!strcmp(wid->widget->url, url) && !wid->activated) break;
+ wid = NULL;
+ }
+ if (!wid) {
+ wid = wm_load_widget(wm, url, 0, 1);
+ }
+ if (url) gf_free(url);
+
+ /*parse context if any*/
+ if (wid && wid->mpegu_context) {
+ gf_xml_dom_del(wid->mpegu_context);
+ wid->mpegu_context = NULL;
+ }
+ if (wid && widget_ctx && strlen(widget_ctx)) {
+ GF_Err e;
+ GF_XMLNode *context = NULL;
+ wid->mpegu_context = gf_xml_dom_new();
+ e = gf_xml_dom_parse_string(wid->mpegu_context, widget_ctx);
+ if (!e) {
+ context = gf_xml_dom_get_root(wid->mpegu_context);
+ if (strcmp(context->name, "contextInformation")) context = NULL;
+ } else {
+ }
+
+ if (!context && wid->mpegu_context) {
+ gf_xml_dom_del(wid->mpegu_context);
+ wid->mpegu_context = NULL;
+ }
+ }
+
+ if (wid) {
+ wm_widget_jsbind(wm, wid);
+ SMJS_SET_RVAL(OBJECT_TO_JSVAL(wid->obj));
+ }
+ SMJS_FREE(c, manifest);
+ SMJS_FREE(c, widget_ctx);
+ return JS_TRUE;
+}
+
+static JSBool SMJS_FUNCTION(wm_unload)
+{
+ GF_WidgetInstance *wid;
+ SMJS_OBJ
+ SMJS_ARGS
+ GF_WidgetManager *wm = (GF_WidgetManager *)JS_GetPrivate(c, obj);
+ if (!argc || !JSVAL_IS_OBJECT(argv[0])) return JS_TRUE;
+
+ if (!JS_InstanceOf(c, JSVAL_TO_OBJECT(argv[0]), &wm->wmWidgetClass, NULL) ) return JS_FALSE;
+ wid = (GF_WidgetInstance *)JS_GetPrivate(c, JSVAL_TO_OBJECT(argv[0]) );
+ if (!wid) return JS_TRUE;
+
+ /*unless explecetely requested, remove the section*/
+ if ((argc!=2) || !JSVAL_IS_BOOLEAN(argv[1]) || (JSVAL_TO_BOOLEAN(argv[1])==JS_TRUE) ) {
+ /*create section*/
+ gf_cfg_del_section(wm->term->user->config, wid->secname);
+ gf_cfg_set_key(wm->term->user->config, "Widgets", wid->secname, NULL);
+ }
+ wm_delete_widget_instance(wm, wid);
+ return JS_TRUE;
+}
+
+
+
+static JSBool wm_getProperty(JSContext *c, JSObject *obj, SMJS_PROP_GETTER, jsval *vp)
+{
+ char *prop_name;
+ GF_WidgetManager *wm = (GF_WidgetManager *)JS_GetPrivate(c, obj);
+ if (!wm) return JS_FALSE;
+
+ if (!SMJS_ID_IS_STRING(id)) return JS_TRUE;
+ prop_name = SMJS_CHARS_FROM_STRING(c, SMJS_ID_TO_STRING(id));
+ if (!prop_name) return JS_FALSE;
+
+ if (!strcmp(prop_name, "num_widgets")) {
+ *vp = INT_TO_JSVAL(gf_list_count(wm->widget_instances));
+ }
+ else if (!strcmp(prop_name, "last_widget_dir")) {
+ const char *opt = gf_cfg_get_key(wm->term->user->config, "Widgets", "last_widget_dir");
+ if (!opt) opt = "/";
+ *vp = STRING_TO_JSVAL(JS_NewStringCopyZ(c, opt));
+ }
+ SMJS_FREE(c, prop_name);
+ return JS_TRUE;
+}
+static JSBool wm_setProperty(JSContext *c, JSObject *obj, SMJS_PROP_SETTER, jsval *vp)
+{
+ char *prop_name;
+ GF_WidgetManager *wm = (GF_WidgetManager *)JS_GetPrivate(c, obj);
+ if (!wm) return JS_FALSE;
+
+ if (!JSVAL_IS_STRING(*vp)) return JS_TRUE;
+ if (!SMJS_ID_IS_STRING(id)) return JS_TRUE;
+ prop_name = SMJS_CHARS_FROM_STRING(c, SMJS_ID_TO_STRING(id));
+
+ if (!strcmp(prop_name, "last_widget_dir")) {
+ char *v = SMJS_CHARS(c, *vp);
+ gf_cfg_set_key(wm->term->user->config, "Widgets", "last_widget_dir", v);
+ SMJS_FREE(c, v);
+ }
+ SMJS_FREE(c, prop_name);
+ return JS_TRUE;
+}
+
+static JSBool SMJS_FUNCTION(wm_get)
+{
+ u32 i;
+ GF_WidgetInstance *wid;
+ SMJS_OBJ
+ SMJS_ARGS
+ GF_WidgetManager *wm = (GF_WidgetManager *)JS_GetPrivate(c, obj);
+ if (!argc || !JSVAL_IS_INT(argv[0])) return JS_TRUE;
+
+ i = JSVAL_TO_INT(argv[0]);
+ wid = gf_list_get(wm->widget_instances, i);
+ if (wid) SMJS_SET_RVAL( OBJECT_TO_JSVAL(wid->obj) );
+ return JS_TRUE;
+}
+
+static JSBool SMJS_FUNCTION(wm_find_interface)
+{
+ char *ifce_name;
+ u32 i;
+ GF_WidgetInstance *wid;
+ SMJS_OBJ
+ SMJS_ARGS
+ GF_WidgetManager *wm = (GF_WidgetManager *)JS_GetPrivate(c, obj);
+ if (!argc || !JSVAL_IS_STRING(argv[0])) return JS_TRUE;
+
+ ifce_name = SMJS_CHARS(c, argv[0]);
+ i=0;
+ while ( (wid = gf_list_enum(wm->widget_instances, &i) )) {
+ u32 j=0;
+ GF_WidgetInterface *wid_ifce;
+ while ((wid_ifce = gf_list_enum(wid->widget->main->interfaces, &j))) {
+ if (!strcmp(wid_ifce->type, ifce_name)) {
+ SMJS_SET_RVAL( OBJECT_TO_JSVAL(wid->obj) );
+ SMJS_FREE(c, ifce_name);
+ return JS_TRUE;
+ }
+ }
+ }
+ SMJS_FREE(c, ifce_name);
+ return JS_TRUE;
+}
+
+
+const char *wm_xml_get_attr(GF_XMLNode *root, const char *name)
+{
+
+ u32 i, count;
+ count = gf_list_count(root->attributes);
+ for (i=0; i<count; i++) {
+ char *sep;
+ GF_XMLAttribute *att = gf_list_get(root->attributes, i);
+ if (!att->name) continue;
+ if (!strcmp(att->name, name)) return att->value;
+ sep = strchr(att->name, ':');
+ if (sep && !strcmp(sep+1, name)) return att->value;
+ }
+ return NULL;
+}
+
+/* TODO Implement real language check according to BCP 47*/
+static Bool wm_check_language(const char *xml_lang_value, const char *user_locale)
+{
+ Bool ret = 0;
+ char *sep, *val;
+ val = (char*)xml_lang_value;
+ while (!ret) {
+ sep = strchr(val, ';');
+ if (sep) sep[0] = 0;
+ if (strstr(user_locale, val)) ret = 1;
+ if (sep) {
+ sep[0] = ';';
+ val = sep+1;
+ } else {
+ break;
+ }
+ }
+ return ret;
+}
+
+static GF_XMLNode *wm_xml_find(GF_XMLNode *root, const char *ns_prefix, const char *name, const char *user_locale)
+{
+ GF_XMLNode *localized = NULL;
+ GF_XMLNode *non_localized = NULL;
+ u32 i, count;
+
+ if (!root) return NULL;
+
+ count = gf_list_count(root->content);
+ for (i=0; i<count; i++) {
+ GF_XMLNode *n = gf_list_get(root->content, i);
+ if (n->type==GF_XML_NODE_TYPE && n->name && !strcmp(n->name, name) && ((!ns_prefix && !n->ns) || (ns_prefix && n->ns && !strcmp(ns_prefix, n->ns)))) {
+ const char *lang = wm_xml_get_attr(n, "xml:lang");
+ if (!lang) {
+ if (!non_localized) non_localized = n;
+ } else {
+ if (user_locale && wm_check_language(lang, user_locale) && !localized) localized = n;
+ }
+ }
+ }
+ if (localized) return localized;
+ else return non_localized;
+}
+
+static GF_WidgetPin *wm_parse_pin(const char *value, u16 type, const char *pin_name, const char *scriptType, const char *default_value)
+{
+ GF_WidgetPin *pin;
+ char *sep;
+
+ if (!value && !scriptType && !default_value) return NULL;
+
+ GF_SAFEALLOC(pin, GF_WidgetPin);
+ pin->type = type;
+ if (pin_name) pin->name = gf_strdup(pin_name);
+
+ if (value) {
+ sep = strrchr(value, '.');
+ if (!sep && (type==GF_WM_PREF_CONNECT)) {
+ gf_free(pin);
+ return NULL;
+ }
+
+ /*node.event || node.attribute*/
+ if (sep) {
+ sep[0] = 0;
+ pin->node = gf_strdup(value);
+ pin->attribute = gf_strdup(sep+1);
+ sep[0] = '.';
+ }
+ /*script function*/
+ else {
+ pin->node = gf_strdup(value);
+ }
+ }
+
+ if (scriptType) {
+ if (!strcmp(scriptType, "boolean")) pin->script_type = GF_WM_PARAM_SCRIPT_BOOL;
+ else if (!strcmp(scriptType, "number")) pin->script_type = GF_WM_PARAM_SCRIPT_NUMBER;
+ } else if (default_value) {
+ pin->default_value = gf_strdup(default_value);
+ }
+ return pin;
+}
+
+static void wm_parse_mpegu_content_element(GF_WidgetContent *content, GF_XMLNode *root, const char *ns_prefix, GF_List *global_prefs)
+{
+ GF_XMLNode *ifces, *context, *pref_node;
+ GF_WidgetMessage *msg;
+ GF_WidgetInterface *ifce;
+ GF_XMLNode *ifce_node;
+ GF_WidgetPreference *pref;
+ const char *att;
+ u32 i = 0;
+
+ ifces = wm_xml_find(root, ns_prefix, "interfaces", NULL);
+ if (ifces) {
+
+ /*get all interface element*/
+ while ((ifce_node = gf_list_enum(ifces->content, &i))) {
+ GF_XMLNode *msg_node;
+ u32 j;
+ const char *ifce_type, *act;
+ if (ifce_node->type != GF_XML_NODE_TYPE) continue;
+ if (strcmp(ifce_node->name, "interface")) continue;
+ ifce_type = wm_xml_get_attr(ifce_node, "type");
+ if (!ifce_type) continue;
+
+ GF_SAFEALLOC(ifce, GF_WidgetInterface);
+ ifce->type = gf_strdup(ifce_type);
+ ifce->messages = gf_list_new();
+ ifce->content = content;
+ gf_list_add(content->interfaces, ifce);
+
+ act = wm_xml_get_attr(ifce_node, "serviceProvider");
+ if (act && !strcmp(act, "true")) ifce->provider = 1;
+
+ act = wm_xml_get_attr(ifce_node, "multipleBindings");
+ if (act && !strcmp(act, "true")) ifce->multiple_binding = 1;
+
+ act = wm_xml_get_attr(ifce_node, "required");
+ if (act && !strcmp(act, "true")) ifce->required = 1;
+
+ act = wm_xml_get_attr(ifce_node, "connectTo");
+ if (act) ifce->connectTo = gf_strdup(act);
+
+ act = wm_xml_get_attr(ifce_node, "bindAction");
+ if (act) {
+ ifce->bind_action = wm_parse_pin(act, GF_WM_BIND_ACTION, NULL, NULL, NULL);
+ }
+ act = wm_xml_get_attr(ifce_node, "unbindAction");
+ if (act) {
+ ifce->unbind_action = wm_parse_pin(act, GF_WM_UNBIND_ACTION, NULL, NULL, NULL);
+ }
+
+ j=0;
+ while ((msg_node = gf_list_enum(ifce_node->content, &j))) {
+ u32 k;
+ GF_XMLNode *par_node;
+ const char *msg_name, *action;
+ if (msg_node->type != GF_XML_NODE_TYPE) continue;
+ if (strcmp(msg_node->name, "messageIn") && strcmp(msg_node->name, "messageOut")) continue;
+
+ msg_name = wm_xml_get_attr(msg_node, "name");
+ if (!msg_name) continue;
+ GF_SAFEALLOC(msg, GF_WidgetMessage);
+ msg->name = gf_strdup(msg_name);
+ msg->params = gf_list_new();
+ msg->ifce = ifce;
+ if (!strcmp(msg_node->name, "messageOut")) msg->is_output = 1;
+
+ gf_list_add(ifce->messages, msg);
+
+ /*get inputAction*/
+ action = wm_xml_get_attr(msg_node, "inputAction");
+ if (action) {
+ msg->input_action = wm_parse_pin(action, GF_WM_INPUT_ACTION, NULL, NULL, NULL);
+ }
+
+ /*get outputTrigger*/
+ action = wm_xml_get_attr(msg_node, "outputTrigger");
+ if (action) {
+ msg->output_trigger = wm_parse_pin(action, GF_WM_OUTPUT_TRIGGER, NULL, NULL, NULL);
+ }
+
+ /*get params*/
+ k=0;
+ while ((par_node=gf_list_enum(msg_node->content, &k))) {
+ GF_WidgetPin *wpin;
+ u16 type;
+ const char *par_name, *att_name;
+ if (par_node->type != GF_XML_NODE_TYPE) continue;
+ if (strcmp(par_node->name, "input") && strcmp(par_node->name, "output")) continue;
+
+
+ par_name = wm_xml_get_attr(par_node, "name");
+ /*invalid param, discard message*/
+ if (!par_name) {
+ gf_list_del_item(ifce->messages, msg);
+ gf_list_del(msg->params);
+ gf_free(msg->name);
+ gf_free(msg);
+ break;
+ }
+
+ if (!strcmp(par_node->name, "output")) {
+ type = GF_WM_PARAM_OUTPUT;
+ att_name = wm_xml_get_attr(par_node, "attributeModified");
+ } else {
+ type = GF_WM_PARAM_INPUT;
+ att_name = wm_xml_get_attr(par_node, "setAttribute");
+ }
+ wpin = wm_parse_pin(att_name, type, par_name, wm_xml_get_attr(par_node, "scriptParamType"), wm_xml_get_attr(par_node, "default"));
+ if (!wpin) continue;
+ wpin->msg = msg;
+
+ gf_list_add(msg->params, wpin);
+ }
+ }
+ }
+ }
+
+ /*get all component elements*/
+ i=0;
+ while (root && (ifce_node = gf_list_enum(root->content, &i))) {
+ GF_XMLNode *req_node;
+ u32 j;
+ const char *src, *id, *act;
+ GF_WidgetComponent *comp;
+ if (ifce_node->type != GF_XML_NODE_TYPE) continue;
+ if (strcmp(ifce_node->name, "component")) continue;
+ src = wm_xml_get_attr(ifce_node, "src");
+ id = wm_xml_get_attr(ifce_node, "id");
+
+ GF_SAFEALLOC(comp, GF_WidgetComponent);
+ comp->required_interfaces = gf_list_new();
+ comp->content = content;
+ if (id) comp->id = gf_strdup(id);
+ if (src) comp->src = gf_strdup(src);
+ j=0;
+ while ((req_node=gf_list_enum(ifce_node->content, &j))) {
+ const char *ifce_type;
+ if (req_node->type != GF_XML_NODE_TYPE) continue;
+ if (strcmp(req_node->name, "requiredInterface")) continue;
+ ifce_type = wm_xml_get_attr(req_node, "type");
+ if (!ifce_type) continue;
+ gf_list_add(comp->required_interfaces, gf_strdup(ifce_type));
+ }
+
+ act = wm_xml_get_attr(ifce_node, "activateTrigger");
+ if (act) comp->activateTrigger = wm_parse_pin(act, GF_WM_ACTIVATE_TRIGGER, NULL, NULL, NULL);
+ act = wm_xml_get_attr(ifce_node, "deactivateTrigger");
+ if (act) comp->deactivateTrigger = wm_parse_pin(act, GF_WM_DEACTIVATE_TRIGGER, NULL, NULL, NULL);
+
+ gf_list_add(content->components, comp);
+ }
+
+ /*clone global prefs for this content*/
+ i=0;
+ while ((pref = gf_list_enum(global_prefs, &i))) {
+ GF_WidgetPreference *apref;
+ GF_SAFEALLOC(apref, GF_WidgetPreference);
+ apref->name = gf_strdup(pref->name);
+ if (pref->value) apref->value = gf_strdup(pref->value);
+ apref->flags = pref->flags;
+ gf_list_add(content->preferences, apref);
+ }
+
+ context = wm_xml_find(root, ns_prefix, "contextConfiguration", NULL);
+ if (context) {
+ u32 j;
+ /*get all preference elements*/
+ i=0;
+ while ((pref_node = gf_list_enum(context->content, &i))) {
+ const char *att;
+ if (pref_node->type != GF_XML_NODE_TYPE) continue;
+ if (strcmp(pref_node->name, "preferenceConnect")) continue;
+ att = wm_xml_get_attr(pref_node, "name");
+ if (!att) continue;
+
+ j=0;
+ while ((pref = gf_list_enum(content->preferences, &j))) {
+ if (!strcmp(pref->name, att) && !pref->connectTo) break;
+ }
+
+ if (!pref) {
+ GF_SAFEALLOC(pref, GF_WidgetPreference);
+ pref->name = gf_strdup(att);
+ gf_list_add(content->preferences, pref);
+ }
+ att = wm_xml_get_attr(pref_node, "value");
+ if (att) {
+ if (pref->value) gf_free(pref->value);
+ pref->value = gf_strdup(att);
+ }
+ att = wm_xml_get_attr(pref_node, "readOnly");
+ if (att && !strcmp(att, "true")) pref->flags |= GF_WM_PREF_READONLY;
+ att = wm_xml_get_attr(pref_node, "migratable");
+ if (att && !strcmp(att, "saveOnly")) pref->flags |= GF_WM_PREF_SAVE;
+ else if (att && !strcmp(att, "migrateOnly")) pref->flags |= GF_WM_PREF_MIGRATE;
+ else pref->flags |= GF_WM_PREF_SAVE | GF_WM_PREF_MIGRATE;
+
+ att = wm_xml_get_attr(pref_node, "connectTo");
+ if (att) pref->connectTo = wm_parse_pin(att, GF_WM_PREF_CONNECT, NULL, NULL, NULL);
+ }
+
+ att = wm_xml_get_attr(context, "savedAction");
+ if (att) content->savedAction = wm_parse_pin(att, GF_WM_PREF_SAVEDACTION, NULL, NULL, NULL);
+ att = wm_xml_get_attr(context, "restoredAction");
+ if (att) content->restoredAction = wm_parse_pin(att, GF_WM_PREF_RESTOREDACTION, NULL, NULL, NULL);
+ att = wm_xml_get_attr(context, "saveTrigger");
+ if (att) content->saveTrigger = wm_parse_pin(att, GF_WM_PREF_SAVETRIGGER, NULL, NULL, NULL);
+ att = wm_xml_get_attr(context, "restoreTrigger");
+ if (att) content->restoreTrigger = wm_parse_pin(att, GF_WM_PREF_RESTORETRIGGER, NULL, NULL, NULL);
+ }
+}
+
+/* Implements the W3C P&C rule for getting a single attribute value
+ see http://www.w3.org/TR/widgets/#rule-for-getting-a-single-attribute-valu0
+ should be different from getting normalized text but for now it's ok
+ */
+static char *wm_get_single_attribute(const char *input) {
+ u32 i, j, len;
+ char *output;
+ Bool first_space_copied;
+
+ if (!input) return gf_strdup("");
+
+ len = strlen(input);
+ output = gf_malloc(len+1);
+
+ first_space_copied = 1;
+ j = 0;
+ for (i = 0; i<len; i++) {
+ switch (input[i]) {
+ case ' ':
+ case '\t':
+ case '\r':
+ case '\n':
+ if (!first_space_copied) {
+ output[j] = ' ';
+ j++;
+ first_space_copied = 1;
+ }
+ break;
+ default:
+ output[j] = input[i];
+ j++;
+ first_space_copied = 0;
+ }
+ }
+ if (j && output[j-1] == ' ') output[j-1] = 0;
+ output[j] = 0;
+ return output;
+}
+
+/* Implements the W3C P&C rule for getting a single attribute value
+ see http://www.w3.org/TR/widgets/#rule-for-getting-a-single-attribute-valu0 */
+static u32 wm_parse_non_neg(const char *input) {
+ u32 result = 0;
+ if (strlen(input) && !strchr(input, '-')) {
+ if (sscanf(input, "%u", &result) != 1) result = 0;
+ }
+ return result;
+}
+
+/* returns the localized concatenated text content
+see http://www.w3.org/TR/2004/REC-DOM-Level-3-Core-20040407/core.html#Node3-textContent
+and http://www.w3.org/TR/widgets/#rule-for-getting-text-content0
+*/
+static char *wm_get_text_content(GF_XMLNode *node, char *inherited_locale, const char *user_locale) {
+ if (node->type == GF_XML_TEXT_TYPE) {
+ if (node->name) return gf_strdup(node->name);
+ else return gf_strdup("");
+ } else {
+ char *xml_lang = (char *)wm_xml_get_attr(node, "xml:lang");
+ if (!xml_lang) xml_lang = inherited_locale;
+ /*
+ if (xml_lang && user_locale && wm_check_language(xml_lang, user_locale))
+ */
+ {
+ u32 i, count;
+ char *text_content;
+ u32 text_content_len = 0;
+ text_content = gf_strdup("");
+ count = gf_list_count(node->content);
+ for (i=0; i<count; i++) {
+ GF_XMLNode *child = (GF_XMLNode *)gf_list_get(node->content, i);
+ char *child_content = wm_get_text_content(child, xml_lang, user_locale);
+ u32 child_content_len = strlen(child_content);
+ text_content = gf_realloc(text_content, text_content_len+child_content_len+1);
+ memcpy(text_content+text_content_len, child_content, child_content_len);
+ text_content[text_content_len+child_content_len] = 0;
+ text_content_len+=child_content_len;
+ gf_free(child_content);
+ }
+ return text_content;
+ }
+ /*
+ } else {
+ return gf_strdup("");
+ */
+ }
+}
+
+static char *wm_get_normalized_text_content(GF_XMLNode *node, char *inherited_locale, const char *user_locale) {
+ char *text_content, *result;
+ /* first aggregate text content */
+ text_content = wm_get_text_content(node, inherited_locale, user_locale);
+ /* calling normalization of text content */
+ result = wm_get_single_attribute(text_content);
+ gf_free(text_content);
+ return result;
+}
+
+/* When relocating resources over HTTP, we check if the resources for a given locale exists
+ on the server by sending a HEAD message with an Accept-Language header. */
+void wm_relocate_proc(void *usr_cbk, GF_NETIO_Parameter *parameter)
+{
+ switch (parameter->msg_type) {
+ case GF_NETIO_GET_METHOD:
+ parameter->name = "HEAD";
+ break;
+ }
+}
+
+/* relocate the given resource name (res_name) using registered relocators (e.g. locales, package folder)
+ The result is the path of the file, possibly uncompressed, possibly localized.
+ The parameter widget_path provides the path for converting relative resource paths into absolute paths.*/
+static Bool wm_relocate_url(GF_WidgetManager *wm, const char *widget_path, const char *res_name, char *relocated_name, char *localized_res_name)
+{
+ Bool ok = 0;
+ char *res_url;
+ Bool result = gf_term_relocate_url(wm->term, res_name, widget_path, relocated_name, localized_res_name);
+ if (result) return result;
+
+ res_url = gf_url_concatenate(widget_path, res_name);
+
+ /*try with HTTP HEAD */
+ if (!strnicmp(widget_path, "http", 4)) {
+ GF_Err e;
+ /*fetch the remote widget manifest synchronously and load it */
+ GF_DownloadSession *sess = gf_dm_sess_new(wm->term->downloader, (char *)res_url, GF_NETIO_SESSION_NOT_THREADED, wm_relocate_proc, NULL, &e);
+ if (sess) {
+ e = gf_dm_sess_process(sess);
+ gf_dm_sess_del(sess);
+ if (e==GF_OK) {
+ const char *opt = gf_cfg_get_key(wm->term->user->config, "Systems", "Language2CC");
+ strcpy(relocated_name, res_url);
+ if (opt)
+ sprintf(localized_res_name, "%s/%s", opt, res_name);
+ else
+ strcpy(localized_res_name, res_name);
+ ok = 1;
+ }
+ }
+ }
+ gf_free(res_url);
+ return ok;
+}
+
+/* function that checks if the default start file exists in the widget (package or folder)
+ according to the default start files table from the W3C P&C spec.
+ The widget path attribute is used to get the associated relocator from the registered relocators */
+static void wm_set_default_start_file(GF_WidgetManager *wm, GF_WidgetContent *content, const char *widget_path) {
+ Bool result;
+ char localized_path[GF_MAX_PATH], relocated_path[GF_MAX_PATH];
+ char *mimetype = "text/html";
+ result = wm_relocate_url(wm, widget_path, "index.htm", relocated_path, localized_path);
+ if (result) {
+ mimetype = "text/html";
+ } else {
+ result = wm_relocate_url(wm, widget_path, "index.html", relocated_path, localized_path);
+ if (result) {
+ mimetype = "text/html";
+ } else {
+ result = wm_relocate_url(wm, widget_path, "index.svg", relocated_path, localized_path);
+ if (result) {
+ mimetype = "image/svg+xml";
+ } else {
+ result = wm_relocate_url(wm, widget_path, "index.xhtml", relocated_path, localized_path);
+ if (result) {
+ mimetype = "application/xhtml+xml";
+ } else {
+ result = wm_relocate_url(wm, widget_path, "index.xht", relocated_path, localized_path);
+ if (result) mimetype = "application/xhtml+xml";
+ }
+ }
+ }
+ }
+ if (content->src) gf_free(content->src);
+ content->src = gf_strdup(localized_path);
+ if (content->relocated_src) gf_free(content->relocated_src);
+ content->relocated_src = gf_strdup(relocated_path);
+ if (content->mimetype) gf_free(content->mimetype);
+ content->mimetype = gf_strdup(mimetype);
+ if (content->encoding) gf_free(content->encoding);
+ content->encoding = gf_strdup("utf-8");
+}
+
+static GF_WidgetContent *wm_add_icon(GF_Widget *widget, const char *icon_relocated_path, const char *icon_localized_path, const char *uri_fragment)
+{
+ GF_WidgetContent *icon;
+ u32 i, count;
+ Bool already_in = 0;
+
+ count = gf_list_count(widget->icons);
+ for (i =0; i<count; i++) {
+ GF_WidgetContent *in_icon = gf_list_get(widget->icons, i);
+ if (!strcmp(icon_localized_path, in_icon->src)) {
+ already_in = 1;
+ break;
+ }
+ }
+ if (already_in) return NULL;
+
+ GF_SAFEALLOC(icon, GF_WidgetContent);
+ if (uri_fragment) {
+ icon->src = gf_malloc(strlen(icon_localized_path) + strlen(uri_fragment) + 1);
+ strcpy(icon->src, icon_localized_path);
+ strcat(icon->src, uri_fragment);
+
+ icon->relocated_src = gf_malloc(strlen(icon_relocated_path) + strlen(uri_fragment) + 1);
+ strcpy(icon->relocated_src, icon_relocated_path);
+ strcat(icon->relocated_src, uri_fragment);
+ } else {
+ icon->src = gf_strdup(icon_localized_path);
+ icon->relocated_src = gf_strdup(icon_relocated_path);
+ }
+ icon->interfaces = gf_list_new();
+ icon->components = gf_list_new();
+ icon->preferences = gf_list_new();
+ icon->widget = widget;
+ gf_list_add(widget->icons, icon);
+ return icon;
+}
+
+/* Scans the W3C default icons table and add each icon */
+static void wm_set_default_icon_files(GF_WidgetManager *wm, const char *widget_path, GF_Widget *widget) {
+ char relocated_path[GF_MAX_PATH], localized_path[GF_MAX_PATH];
+ Bool result;
+
+ result = wm_relocate_url(wm, widget_path, "icon.svg", relocated_path, localized_path);
+ if (result) wm_add_icon(widget, relocated_path, localized_path, NULL);
+
+ result = wm_relocate_url(wm, widget_path, "icon.ico", relocated_path, localized_path);
+ if (result) wm_add_icon(widget, relocated_path, localized_path, NULL);
+
+ result = wm_relocate_url(wm, widget_path, "icon.png", relocated_path, localized_path);
+ if (result) wm_add_icon(widget, relocated_path, localized_path, NULL);
+
+ result = wm_relocate_url(wm, widget_path, "icon.gif", relocated_path, localized_path);
+ if (result) wm_add_icon(widget, relocated_path, localized_path, NULL);
+
+ result = wm_relocate_url(wm, widget_path, "icon.jpg", relocated_path, localized_path);
+ if (result) wm_add_icon(widget, relocated_path, localized_path, NULL);
+}
+
+GF_WidgetInstance *wm_load_widget(GF_WidgetManager *wm, const char *path, u32 InstanceID, Bool skip_context)
+{
+ char szName[GF_MAX_PATH];
+ u32 i, count;
+ GF_Widget *widget = NULL;
+ GF_WidgetInstance *wi = NULL;
+ GF_XMLNode *root, *icon, *nmain, *name, *xml_node;
+ GF_Err e;
+ GF_DOMParser *dom = NULL;
+ GF_WidgetPackage *wpackage = NULL;
+
+ GF_DownloadSession *sess = NULL;
+ const char *widget_ns_prefix = NULL;
+ const char *mpegu_ns_prefix = NULL;
+ const char *user_locale = gf_cfg_get_key(wm->term->user->config, "Systems", "Language2CC");
+
+ /* Try to see if this widget is already loaded */
+ e = GF_OK;
+ count = gf_list_count(wm->widgets);
+ for (i=0; i<count; i++) {
+ widget = gf_list_get(wm->widgets, i);
+ if (!strcmp(widget->url, path)) break;
+ widget = NULL;
+ }
+
+ /*not found, retrieve the widget (if http), check the package if needed and parse the configuration document/widget manifest*/
+ if (!widget) {
+ Bool isDownloadedPackage = 0;
+
+ /* path used to locate the widget (config.xml if unpackaged or zip/isoff package), potentially after download */
+ const char *szLocalPath = path;
+ /* used to locate the config document/widget manifest potentially after unzipping */
+ const char *szManifestPath = path;
+ /* */
+ const char *szWidgetPath = path;
+ const char *desc;
+ GF_WidgetPreference *pref;
+ GF_List *global_prefs;
+ GF_WidgetContent *content;
+ Bool correct_ns = 0;
+
+ if (strstr(path, "http://")) {
+ /*fetch the remote widget manifest synchronously and load it */
+ sess = gf_dm_sess_new(wm->term->downloader, (char *)path, GF_NETIO_SESSION_NOT_THREADED, NULL, NULL, &e);
+ if (sess) {
+ e = gf_dm_sess_process(sess);
+ if (e==GF_OK) {
+ szLocalPath = gf_dm_sess_get_cache_name(sess);
+
+ if (gf_unzip_probe(szLocalPath)) {
+ isDownloadedPackage = 1;
+ } else {
+ /* TODO ISOFF-based packaged widget */
+ }
+ }
+ }
+ if (!sess || (e!=GF_OK) || !szLocalPath) goto exit;
+ }
+
+ /* Check if the widget package is a valid package and if it contains a config.xml file */
+ szManifestPath = szLocalPath;
+
+ wpackage = widget_package_new(wm, szLocalPath);
+ if (wpackage) {
+ count = gf_list_count(wpackage->resources);
+ for (i=0; i<count; i++) {
+ GF_WidgetPackageResource *wu = gf_list_get(wpackage->resources, i);
+ /* According to W3C WPC, the config.xml file (lower case) shall only be located
+ at the root of the package
+ see http://www.w3.org/TR/widgets/#ta-dxzVDWpaWg */
+ if (!strcmp(wu->inner_path, "config.xml")) {
+ szManifestPath = wu->extracted_path;
+ break;
+ }
+ }
+ szWidgetPath = szManifestPath;
+ }
+
+
+ /* Parse the Widget Config Document as a DOM */
+ dom = gf_xml_dom_new();
+ e = gf_xml_dom_parse(dom, szManifestPath, NULL, NULL);
+ if (e) goto exit;
+
+ root = gf_xml_dom_get_root(dom);
+ if (!root) goto exit;
+
+ correct_ns = 0;
+ count = gf_list_count(root->attributes);
+ for (i=0; i<count; i++) {
+ GF_XMLAttribute *att = gf_list_get(root->attributes, i);
+ if (att->name) {
+ if (!strcmp(att->name, "xmlns")) {
+ if (!strcmp(att->value, "http://www.w3.org/ns/widgets")) {
+ correct_ns = 1;
+ }
+ } else if (!strnicmp(att->name, "xmlns:", 6)) {
+ if (!strcmp(att->value, "http://www.w3.org/ns/widgets")) {
+ widget_ns_prefix = att->name+6;
+ correct_ns = 1;
+ } else if (!strcmp(att->value, "urn:mpeg:mpegu:schema:widgets:manifest:2010")) {
+ mpegu_ns_prefix = att->name+6;
+ }
+ }
+ }
+ }
+ /* According to the spec, wrong or no namespace means invalid widget
+ see http://www.w3.org/TR/widgets/#ta-ACCJfDGwDQ */
+ if (!correct_ns) goto exit;
+
+ /* see http://www.w3.org/TR/widgets/#ta-ACCJfDGwDQ */
+ if ((root->ns && (!widget_ns_prefix || strcmp(root->ns, widget_ns_prefix) || strcmp(root->name, "widget"))) ||
+ (!root->ns && (widget_ns_prefix || strcmp(root->name, "widget"))))
+ goto exit;
+
+
+ /*pre-parse the root-level preference for use when parsing MPEG-U elements */
+ global_prefs = gf_list_new();
+ i=0;
+ while ((nmain = gf_list_enum(root->content, &i))) {
+ const char *pname, *pvalue;
+ /* 'normalized' preference name and readonly*/
+ char *npname, *npro;
+ u32 i, count;
+ Bool pref_exists = 0;
+ Bool readOnly = 0;
+ if (nmain->type != GF_XML_NODE_TYPE) continue;
+ if (strcmp(nmain->name, "preference")) continue;
+ pname = wm_xml_get_attr(nmain, "name");
+ npname = wm_get_single_attribute(pname);
+ if (!npname || !strlen(npname)) continue;
+
+ count = gf_list_count(global_prefs);
+ for (i = 0; i < count; i++) {
+ GF_WidgetPreference *tmp_pref = gf_list_get(global_prefs, i);
+ if (!strcmp(tmp_pref->name, npname)) {
+ pref_exists = 1;
+ break;
+ }
+ }
+ if (pref_exists) continue;
+
+ pvalue = wm_xml_get_attr(nmain, "readonly");
+ npro = wm_get_single_attribute(pvalue);
+ if (npro && strlen(npro) && !strcmp(npro, "true")) readOnly=1;
+ if (npro) gf_free(npro);
+
+ pvalue = wm_xml_get_attr(nmain, "value");
+
+ GF_SAFEALLOC(pref, GF_WidgetPreference);
+ pref->name = npname;
+ if (pvalue) pref->value = wm_get_single_attribute(pvalue);
+ /*global preferences are save and migratable*/
+ pref->flags = GF_WM_PREF_SAVE | GF_WM_PREF_MIGRATE;
+ if (readOnly) pref->flags |= GF_WM_PREF_READONLY;
+ gf_list_add(global_prefs, pref);
+ }
+
+ /* get the content element from the XML Config document */
+ GF_SAFEALLOC(content, GF_WidgetContent);
+ content->interfaces = gf_list_new();
+ content->components = gf_list_new();
+ content->preferences = gf_list_new();
+ nmain = wm_xml_find(root, widget_ns_prefix, "content", NULL);
+ if (!nmain) {
+ /* if not found, use the default table of start files */
+ wm_set_default_start_file(wm, content, szWidgetPath);
+ } else {
+ const char *src, *encoding, *mimetype;
+ src = wm_xml_get_attr(nmain, "src");
+
+ /*check the resource exists*/
+ if (src) {
+ Bool result;
+ char relocated_path[GF_MAX_PATH], localized_path[GF_MAX_PATH];
+ /*remove any existing fragment*/
+ char *sep = strchr(src, '#');
+ if (sep) sep[0] = 0;
+ result = wm_relocate_url(wm, szWidgetPath, src, relocated_path, localized_path);
+ if (sep) sep[0] = '#';
+ if (result) {
+ content->relocated_src = gf_strdup(relocated_path);
+ content->src = gf_strdup(localized_path);
+ }
+ }
+
+ encoding = wm_xml_get_attr(nmain, "encoding");
+ if (encoding && strlen(encoding)) content->encoding = wm_get_single_attribute(encoding);
+ else content->encoding = gf_strdup("utf-8");
+
+ mimetype = wm_xml_get_attr(nmain, "type");
+ if (mimetype && strlen(mimetype)) {
+ char *sep = strchr(mimetype, ';');
+ if (sep) sep[0] = 0;
+ content->mimetype = wm_get_single_attribute(mimetype);
+ if (sep) sep[0] = ';';
+ }
+ else content->mimetype = gf_strdup("text/html");
+
+ if (!content->relocated_src) wm_set_default_start_file(wm, content, szWidgetPath);
+ }
+ if (strlen(content->relocated_src) == 0) {
+ gf_list_del(content->interfaces);
+ gf_list_del(content->components);
+ gf_list_del(content->preferences);
+ gf_free(content);
+ content = NULL;
+ goto exit;
+ }
+ /* We need to call the parse of the MPEG-U elements to clone the global preferences into widget preferences,
+ this should probably be changed to extract the clone from that function */
+ wm_parse_mpegu_content_element(content, nmain, mpegu_ns_prefix, global_prefs);
+
+ GF_SAFEALLOC(widget, GF_Widget);
+ widget->url = gf_strdup(path);
+ widget->manifest_path = gf_strdup(szManifestPath);
+ if (isDownloadedPackage) widget->local_path = gf_strdup(szLocalPath);
+ widget->wm = wm;
+ widget->main = content;
+ content->widget = widget;
+ widget->icons = gf_list_new();
+ widget->features = gf_list_new();
+ if (wpackage) {
+ widget->wpack = wpackage;
+ wpackage->widget = widget;
+ /*attach downloader to our package to avoid destroying the cache file*/
+ wpackage->sess = sess;
+ sess = NULL;
+ }
+
+ /*check for icon - can be optional*/
+ i=0;
+ while ((icon = gf_list_enum(root->content, &i))) {
+ if (icon->type==GF_XML_NODE_TYPE &&
+ icon->name && !strcmp(icon->name, "icon") &&
+ ((!widget_ns_prefix && !icon->ns) || !strcmp(widget_ns_prefix, icon->ns))) {
+ char *sep;
+ char relocated[GF_MAX_PATH], localized_path[GF_MAX_PATH];
+ char *icon_width, *icon_height;
+ GF_WidgetContent *iconic;
+ Bool result;
+
+ char *pname = (char *)wm_xml_get_attr(icon, "src");
+ if (!pname || !strlen(pname)) continue;
+
+ /*remove any existing fragment*/
+ sep = strchr(pname, '#');
+ if (sep) sep[0] = 0;
+ result = wm_relocate_url(wm, szWidgetPath, pname, relocated, localized_path);
+ if (sep) sep[0] = '#';
+ if (!result) continue;
+
+ iconic = wm_add_icon(widget, relocated, localized_path, sep);
+ if (iconic) {
+ wm_parse_mpegu_content_element(iconic, icon, mpegu_ns_prefix, global_prefs);
+ icon_width = (char *)wm_xml_get_attr(icon, "width");
+ if (icon_width) iconic->width = wm_parse_non_neg(icon_width);
+ icon_height = (char *)wm_xml_get_attr(icon, "height");
+ if (icon_height) iconic->height = wm_parse_non_neg(icon_height);
+ }
+ }
+ }
+ /* after processing the icon elements (wether there are valid icons or not), we use the default icon table
+ see http://dev.w3.org/2006/waf/widgets/test-suite/test-cases/ta-FAFYMEGELU/004/ */
+ wm_set_default_icon_files(wm, szWidgetPath, widget);
+
+ /*delete the root-level preference*/
+ i=0;
+ while ((pref = gf_list_enum(global_prefs , &i))) {
+ if (pref->value) gf_free(pref->value);
+ gf_free(pref->name);
+ gf_free(pref);
+ }
+ gf_list_del(global_prefs);
+
+ /*check for optionnal meta data*/
+ name = wm_xml_find(root, widget_ns_prefix, "name", user_locale);
+ if (name) {
+ const char *shortname = wm_xml_get_attr(name, "short");
+ widget->shortname = wm_get_single_attribute(shortname);
+
+ widget->name = wm_get_normalized_text_content(name, NULL, user_locale);
+ }
+
+ desc = wm_xml_get_attr(root, "id");
+ if (desc) {
+ /* TODO check if this is a valid IRI, for the moment, just hack to pass the test, check for ':'
+ see http://dev.w3.org/2006/waf/widgets/test-suite/test-cases/ta-RawAIWHoMs/ */
+ if (strchr(desc, ':'))
+ widget->identifier = wm_get_single_attribute(desc);
+ }
+
+ desc = wm_xml_get_attr(root, "width");
+ if (desc) {
+ widget->width = wm_parse_non_neg(desc);
+ }
+ desc = wm_xml_get_attr(root, "height");
+ if (desc) {
+ widget->height = wm_parse_non_neg(desc);
+ }
+
+ name = wm_xml_find(root, widget_ns_prefix, "description", user_locale);
+ if (name) {
+ widget->description = wm_get_normalized_text_content(name, NULL, user_locale);
+ }
+
+ name = wm_xml_find(root, widget_ns_prefix, "license", user_locale);
+ if (name) {
+ const char *href = wm_xml_get_attr(name, "href");
+ widget->licenseHref = wm_get_single_attribute(href);
+
+ /* Warning the license text content should not be normalized */
+ widget->license = wm_get_text_content(name, NULL, user_locale);
+ }
+
+ desc = wm_xml_get_attr(root, "version");
+ if (desc) widget->version = wm_get_single_attribute(desc);
+
+ desc = wm_xml_get_attr(root, "uuid");
+ if (desc) widget->uuid = gf_strdup(desc);
+
+ desc = wm_xml_get_attr(root, "discardable");
+ if (desc) widget->discardable = !strcmp(desc, "true") ? 1 : 0;
+
+ desc = wm_xml_get_attr(root, "multipleInstances");
+ if (desc) widget->multipleInstance = !strcmp(desc, "true") ? 1 : 0;
+
+ name = wm_xml_find(root, widget_ns_prefix, "author", NULL);
+ if (name) {
+ desc = wm_xml_get_attr(name, "href");
+ if (desc && strchr(desc, ':')) widget->authorHref = wm_get_single_attribute(desc);
+
+ desc = wm_xml_get_attr(name, "email");
+ widget->authorEmail = wm_get_single_attribute(desc);
+
+ widget->authorName = wm_get_normalized_text_content(name, NULL, user_locale);
+ }
+
+ i=0;
+ while ((xml_node = gf_list_enum(root->content, &i))) {
+ if (xml_node->type==GF_XML_NODE_TYPE &&
+ xml_node->name && !strcmp(xml_node->name, "feature") &&
+ ((!widget_ns_prefix && !xml_node->ns) || !strcmp(widget_ns_prefix, xml_node->ns))) {
+
+ u32 i, count;
+ Bool already_in = 0;
+ GF_WidgetFeature *feat;
+ const char *feature_name, *req_att;
+ char *nfname;
+ Bool required = 1;
+ u32 j;
+ GF_XMLNode *param_node;
+
+ feature_name = (char *)wm_xml_get_attr(xml_node, "name");
+ if (!feature_name || !strlen(feature_name) || !strchr(feature_name, ':')) continue;
+ nfname = wm_get_single_attribute(feature_name);
+
+ req_att = (char *)wm_xml_get_attr(xml_node, "required");
+ if (req_att && !strcmp(req_att, "false")) required = 0;
+
+ count = gf_list_count(widget->features);
+ for (i = 0; i<count; i++) {
+ GF_WidgetFeature *tmp = gf_list_get(widget->features, i);
+ if (!strcmp(nfname, tmp->name)) {
+ already_in = 1;
+ break;
+ }
+ }
+ if (already_in) continue;
+
+ GF_SAFEALLOC(feat, GF_WidgetFeature);
+ feat->name = nfname;
+ feat->required = required;
+ feat->params = gf_list_new();
+ gf_list_add(widget->features, feat);
+
+ j = 0;
+ while ((param_node = gf_list_enum(xml_node->content, &j))) {
+ if (param_node->type==GF_XML_NODE_TYPE &&
+ param_node->name && !strcmp(param_node->name, "param") &&
+ ((!widget_ns_prefix && !param_node->ns) || !strcmp(widget_ns_prefix, param_node->ns))) {
+ GF_WidgetFeatureParam *wfp;
+ const char *param_name, *param_value;
+ char *npname, *npvalue;
+
+ param_name = (char *)wm_xml_get_attr(param_node, "name");
+ npname = wm_get_single_attribute(param_name);
+ if (!strlen(npname)) continue;
+
+ param_value = (char *)wm_xml_get_attr(param_node, "value");
+ npvalue = wm_get_single_attribute(param_value);
+ if (!strlen(npvalue)) {
+ gf_free(npname);
+ continue;
+ }
+
+ GF_SAFEALLOC(wfp, GF_WidgetFeatureParam);
+ wfp->name = npname;
+ wfp->value = npvalue;
+ gf_list_add(feat->params, wfp);
+
+ }
+ }
+
+ }
+ }
+
+ gf_list_add(wm->widgets, widget);
+ }
+
+ GF_SAFEALLOC(wi, GF_WidgetInstance);
+ wi->widget = widget;
+ wi->bound_ifces = gf_list_new();
+ wi->output_triggers = gf_list_new();
+ wi->components = gf_list_new();
+ widget->nb_instances++;
+ wi->instance_id = InstanceID;
+ wi->permanent = 1;
+
+ if (!InstanceID) {
+ char szInst[20];
+
+ count = gf_list_count(wm->widget_instances);
+ for (i=0; i<count; i++) {
+ GF_WidgetInstance *awi = gf_list_get(wm->widget_instances, i);
+ if (awi->widget == wi->widget)
+ wi->instance_id = awi->instance_id;
+ }
+ wi->instance_id ++;
+
+ sprintf(szName, "%s#%s#Instance%d", path, wi->widget->name, wi->instance_id);
+ sprintf(wi->secname, "Widget#%08X", gf_crc_32(szName, strlen(szName)));
+
+ /*create section*/
+ gf_cfg_set_key(wm->term->user->config, "Widgets", wi->secname, " ");
+ gf_cfg_set_key(wm->term->user->config, wi->secname, "WM:Manifest", wi->widget->url);
+ sprintf(szInst, "%d", wi->instance_id);
+ gf_cfg_set_key(wm->term->user->config, wi->secname, "WM:InstanceID", szInst);
+ }
+ gf_list_add(wm->widget_instances, wi);
+
+
+ if (!skip_context && strstr(path, "http://")) {
+ GF_XMLNode *context;
+ GF_DownloadSession *ctx_sess = NULL;
+ char *ctxPath;
+ context = NULL;
+
+ /*fetch the remote widget context synchronously and load it */
+ ctxPath = gf_malloc(sizeof(char) * (strlen(path) + 1 + 15/*?mpeg-u-context*/));
+ strcpy(ctxPath, path);
+ if ((strchr(path, '?') == NULL) && (strstr(path, "%3f")==NULL) && (strstr(path, "%3F")==NULL) ) {
+ strcat(ctxPath, "?mpeg-u-context");
+ } else {
+ strcat(ctxPath, "&mpeg-u-context");
+ }
+
+ /*try to fetch the associated context*/
+ ctx_sess = gf_dm_sess_new(wm->term->downloader, (char *)ctxPath, GF_NETIO_SESSION_NOT_THREADED, NULL, NULL, &e);
+ if (ctx_sess) {
+ e = gf_dm_sess_process(ctx_sess);
+ if (e==GF_OK) {
+ wi->mpegu_context = gf_xml_dom_new();
+ e = gf_xml_dom_parse(wi->mpegu_context , gf_dm_sess_get_cache_name(ctx_sess), NULL, NULL);
+ if (!e) {
+ context = gf_xml_dom_get_root(wi->mpegu_context);
+ if (strcmp(context->name, "contextInformation")) context = NULL;
+ }
+ }
+ gf_dm_sess_del(ctx_sess);
+ e = GF_OK;
+ }
+ gf_free(ctxPath);
+ ctxPath = NULL;
+
+ if (!context && wi->mpegu_context) {
+ gf_xml_dom_del(wi->mpegu_context);
+ wi->mpegu_context = NULL;
+ }
+
+ }
+
+exit:
+ if (dom) gf_xml_dom_del(dom);
+ if (sess) gf_dm_sess_del(sess);
+ if (e || !wi) {
+ if (wi) wm_delete_widget_instance(wm, wi);
+ else {
+ if (wpackage) widget_package_del(wm, wpackage);
+ }
+ return NULL;
+ }
+ return wi;
+}
+
+
+static Bool wm_enum_widget(void *cbk, char *file_name, char *file_path)
+{
+ GF_WidgetInstance *wid;
+ GF_WidgetManager *wm = (GF_WidgetManager *)cbk;
+ wid = wm_load_widget(wm, file_path, 0, 0);
+ if (wid) {
+ wm_widget_jsbind(wm, wid);
+ /*remove section info*/
+ gf_cfg_del_section(wm->term->user->config, wid->secname);
+ gf_cfg_set_key(wm->term->user->config, "Widgets", wid->secname, NULL);
+ }
+ return 0;
+}
+
+static Bool wm_enum_dir(void *cbk, char *file_name, char *file_path)
+{
+ return gf_enum_directory(file_path, 0, wm_enum_widget, cbk, "mgt");
+}
+
+
+static JSBool SMJS_FUNCTION(wm_initialize)
+{
+ u32 i, count;
+ const char*opt;
+ SMJS_OBJ
+ //SMJS_ARGS
+ GF_WidgetManager *wm = (GF_WidgetManager *)JS_GetPrivate(c, obj);
+
+ count = gf_cfg_get_key_count(wm->term->user->config, "Widgets");
+ for (i=0; i<count; i++) {
+ const char *name = gf_cfg_get_key_name(wm->term->user->config, "Widgets", i);
+ /*this is a previously loaded widgets - reload it*/
+ if (!strnicmp(name, "Widget#", 7)) {
+ const char *manifest = gf_cfg_get_key(wm->term->user->config, name, "WM:Manifest");
+ if (manifest) {
+ const char *ID = gf_cfg_get_key(wm->term->user->config, name, "WM:InstanceID");
+ u32 instID = ID ? atoi(ID) : 0;
+ GF_WidgetInstance *wi = wm_load_widget(wm, manifest, instID, 0);
+ if (wi) {
+ strcpy(wi->secname, name);
+ wm_widget_jsbind(wm, wi);
+ }
+ }
+ }
+ }
+
+ opt = gf_cfg_get_key(wm->term->user->config, "Widgets", "WidgetStore");
+ if (opt) gf_enum_directory(opt, 1, wm_enum_dir, wm, NULL);
+
+ return JS_TRUE;
+}
+
+static void widgetmanager_load(GF_JSUserExtension *jsext, GF_SceneGraph *scene, JSContext *c, JSObject *global, Bool unload)
+{
+ GF_WidgetManager *wm;
+
+ GF_JSAPIParam par;
+ JSPropertySpec wmClassProps[] = {
+ {0, 0, 0, 0, 0}
+ };
+ JSFunctionSpec wmClassFuncs[] = {
+ SMJS_FUNCTION_SPEC("initialize", wm_initialize, 0),
+ SMJS_FUNCTION_SPEC("load", wm_load, 2),
+ SMJS_FUNCTION_SPEC("unload", wm_unload, 1),
+ SMJS_FUNCTION_SPEC("get", wm_get, 1),
+ SMJS_FUNCTION_SPEC("findByInterface", wm_find_interface, 1),
+ SMJS_FUNCTION_SPEC(0, 0, 0)
+ };
+
+ wm = jsext->udta;
+ /*widget manager is only loaded once*/
+ if (wm->ctx && (wm->ctx != c)) {
+ /*load the 'Widget' object in the global scope*/
+ widget_load(wm, scene, c, global, unload);
+ return;
+ }
+
+ /*unload widgets*/
+ if (unload) {
+ if (wm->obj) {
+ gf_js_remove_root(wm->ctx, &wm->obj, GF_JSGC_OBJECT);
+ wm->obj = NULL;
+ }
+
+ while (gf_list_count(wm->widget_instances)) {
+ GF_WidgetInstance *widg = gf_list_get(wm->widget_instances, 0);
+ wm_delete_widget_instance(wm, widg);
+ }
+ wm->ctx = NULL;
+ return;
+ }
+ wm->ctx = c;
+
+ if (!scene) return;
+
+ /*setup JS bindings*/
+ JS_SETUP_CLASS(wm->widmanClass, "WIDGETMANAGER", JSCLASS_HAS_PRIVATE, wm_getProperty, wm_setProperty, JS_FinalizeStub);
+
+ JS_InitClass(c, global, 0, &wm->widmanClass, 0, 0, wmClassProps, wmClassFuncs, 0, 0);
+ wm->obj = JS_DefineObject(c, global, "WidgetManager", &wm->widmanClass, 0, 0);
+ JS_SetPrivate(c, wm->obj, wm);
+ gf_js_add_root(c, &wm->obj, GF_JSGC_OBJECT);
+
+
+ {
+ JSPropertySpec wmWidgetClassProps[] = {
+ {0, 0, 0, 0, 0}
+ };
+ JSFunctionSpec wmWidgetClassFuncs[] = {
+ SMJS_FUNCTION_SPEC("activate", wm_widget_activate, 1),
+ SMJS_FUNCTION_SPEC("deactivate", wm_widget_deactivate, 0),
+ SMJS_FUNCTION_SPEC("get_interface", wm_widget_get_interface, 1),
+ SMJS_FUNCTION_SPEC("bind_output_trigger", wm_widget_bind_output_trigger, 2),
+ SMJS_FUNCTION_SPEC("set_input", wm_widget_set_input, 2),
+ SMJS_FUNCTION_SPEC("bind_interface", wm_widget_bind_interface, 2),
+ SMJS_FUNCTION_SPEC("unbind_interface", wm_widget_unbind_interface, 1),
+ SMJS_FUNCTION_SPEC("call_input_action", wm_widget_call_input_action, 1),
+ SMJS_FUNCTION_SPEC("call_input_script", wm_widget_call_input_script, 2),
+ SMJS_FUNCTION_SPEC("is_interface_bound", wm_widget_is_interface_bound, 1),
+ SMJS_FUNCTION_SPEC("get_param_value", wm_widget_get_param_value, 1),
+ SMJS_FUNCTION_SPEC("get_context", wm_widget_get_context, 0),
+ SMJS_FUNCTION_SPEC("get_component", wm_widget_get_component, 2),
+
+ SMJS_FUNCTION_SPEC(0, 0, 0)
+ };
+ /*setup JS bindings*/
+ JS_SETUP_CLASS(wm->wmWidgetClass, "WMWIDGET", JSCLASS_HAS_PRIVATE, wm_widget_getProperty, wm_widget_setProperty, JS_FinalizeStub);
+ JS_InitClass(c, global, 0, &wm->wmWidgetClass, 0, 0, wmWidgetClassProps, wmWidgetClassFuncs, 0, 0);
+
+ JS_SETUP_CLASS(wm->widgetAnyClass, "WIDGETANY", JSCLASS_HAS_PRIVATE, JS_PropertyStub, JS_PropertyStub_forSetter, JS_FinalizeStub);
+ JS_InitClass(c, global, 0, &wm->widgetAnyClass, 0, 0, 0, 0, 0, 0);
+ }
+
+ JS_SETUP_CLASS(wm->widgetClass, "MPEGWidget", JSCLASS_HAS_PRIVATE, widget_getProperty, widget_setProperty, JS_FinalizeStub);
+
+ if (scene->script_action) {
+ if (!scene->script_action(scene->script_action_cbck, GF_JSAPI_OP_GET_TERM, scene->RootNode, &par))
+ return;
+ wm->term = par.term;
+ }
+
+}
+
+
+static GF_JSUserExtension *gwm_new()
+{
+ GF_JSUserExtension *dr;
+ GF_WidgetManager *wm;
+ dr = gf_malloc(sizeof(GF_JSUserExtension));
+ memset(dr, 0, sizeof(GF_JSUserExtension));
+ GF_REGISTER_MODULE_INTERFACE(dr, GF_JS_USER_EXT_INTERFACE, "WidgetManager JavaScript Bindings", "gpac distribution");
+
+ GF_SAFEALLOC(wm, GF_WidgetManager);
+ wm->widget_instances = gf_list_new();
+ wm->widgets = gf_list_new();
+ dr->load = widgetmanager_load;
+ dr->udta = wm;
+ return dr;
+}
+
+
+static void gwm_delete(GF_BaseInterface *ifce)
+{
+ GF_WidgetManager *wm;
+ GF_JSUserExtension *dr = (GF_JSUserExtension *) ifce;
+ if (!dr)
+ return;
+ wm = dr->udta;
+ if (!wm)
+ return;
+ if (wm->widget_instances)
+ gf_list_del(wm->widget_instances);
+ wm->widget_instances = NULL;
+ if (wm->widgets)
+ gf_list_del(wm->widgets);
+ wm->widgets = NULL;
+ gf_free(wm);
+ dr->udta = NULL;
+ gf_free(dr);
+}
+#endif
+
+
+GF_EXPORT
+const u32 *QueryInterfaces()
+{
+ static u32 si [] = {
+#ifdef GPAC_HAS_SPIDERMONKEY
+ GF_JS_USER_EXT_INTERFACE,
+ GF_SCENE_DECODER_INTERFACE,
+#endif
+ 0
+ };
+ return si;
+}
+
+GF_EXPORT
+GF_BaseInterface *LoadInterface(u32 InterfaceType)
+{
+#ifdef GPAC_HAS_SPIDERMONKEY
+ if (InterfaceType == GF_JS_USER_EXT_INTERFACE) return (GF_BaseInterface *)gwm_new();
+ else if (InterfaceType == GF_SCENE_DECODER_INTERFACE) return (GF_BaseInterface *)LoadWidgetReader();
+#endif
+ return NULL;
+}
+
+GF_EXPORT
+void ShutdownInterface(GF_BaseInterface *ifce)
+{
+ switch (ifce->InterfaceType) {
+#ifdef GPAC_HAS_SPIDERMONKEY
+ case GF_JS_USER_EXT_INTERFACE:
+ gwm_delete(ifce);
+ break;
+ case GF_SCENE_DECODER_INTERFACE:
+ ShutdownWidgetReader(ifce);
+ break;
+#endif
+ }
+}
+
--- /dev/null
+//This software module was originally developed by TelecomParisTech in the
+//course of the development of MPEG-U Widgets (ISO/IEC 23007-1) standard.
+//
+//This software module is an implementation of a part of one or
+//more MPEG-U Widgets (ISO/IEC 23007-1) tools as specified by the MPEG-U Widgets
+//(ISO/IEC 23007-1) standard. ISO/IEC gives users of the MPEG-U Widgets
+//(ISO/IEC 23007-1) free license to this software module or modifications
+//thereof for use in hardware or software products claiming conformance to
+//the MPEG-U Widgets (ISO/IEC 23007-1). Those intending to use this software
+//module in hardware or software products are advised that its use may
+//infringe existing patents.
+//The original developer of this software module and his/her company, the
+//subsequent editors and their companies, and ISO/IEC have no liability
+//for use of this software module or modifications thereof in an implementation.
+//Copyright is not released for non MPEG-U Widgets (ISO/IEC 23007-1) conforming
+//products.
+//Telecom ParisTech retains full right to use the code for his/her own purpose,
+//assign or donate the code to a third party and to inhibit third parties from
+//using the code for non MPEG-U Widgets (ISO/IEC 23007-1) conforming products.
+//
+//This copyright notice must be included in all copies or derivative works.
+//
+//Copyright (c) 2009.
+//
+// Alternatively, this software module may be redistributed and/or modified
+// it under the terms of the GNU Lesser General Public License as published by
+// the Free Software Foundation; either version 2, or (at your option)
+// any later version.
+//
+/////////////////////////////////////////////////////////////////////////////////
+
+
+/////////////////////////////////////////////////////////////////////////////////
+//
+// Authors:
+// Jean Le Feuvre, Telecom ParisTech
+// Cyril Concolato, Telecom ParisTech
+//
+/////////////////////////////////////////////////////////////////////////////////
+
+#ifndef _WIDGETMAN_H_
+#define _WIDGETMAN_H_
+
+#include "unzip.h"
+
+/*base SVG type*/
+#include <gpac/modules/js_usr.h>
+
+#ifdef GPAC_HAS_SPIDERMONKEY
+
+#include <gpac/nodes_mpeg4.h>
+#include <gpac/nodes_x3d.h>
+#include <gpac/nodes_svg.h>
+/*dom events*/
+#include <gpac/events.h>
+
+#include <gpac/download.h>
+#include <gpac/crypt.h>
+#include <gpac/network.h>
+#include <gpac/xml.h>
+#include <gpac/internal/scenegraph_dev.h>
+
+
+#include <gpac/isomedia.h>
+
+#include <gpac/internal/smjs_api.h>
+
+#include <gpac/internal/terminal_dev.h>
+#include <gpac/internal/compositor_dev.h>
+
+
+JSBool gf_sg_js_event_add_listener(JSContext *c, JSObject *obj, uintN argc, jsval *argv, jsval *rval, GF_Node *vrml_node);
+JSBool gf_sg_js_event_remove_listener(JSContext *c, JSObject *obj, uintN argc, jsval *argv, jsval *rval, GF_Node *vrml_node);
+
+typedef struct _widget_manager
+{
+ JSContext *ctx;
+ /*widget manager class*/
+ JSClass widmanClass;
+ /*widget class used by the widget manager*/
+ JSClass wmWidgetClass;
+
+ /*widget class used by the widget scripts*/
+ JSClass widgetClass;
+
+ JSClass widgetAnyClass;
+
+ JSObject *obj;
+ GF_Terminal *term;
+ GF_List *widget_instances;
+ /*list of loaded prototypes (eg 1 per all instances of the same widget*/
+ GF_List *widgets;
+} GF_WidgetManager;
+
+
+
+enum
+{
+ GF_WPIN_STRING,
+ GF_WPIN_INTEGER,
+ GF_WPIN_NUMBER,
+};
+
+typedef struct
+{
+ char *inner_path;
+ char *extracted_path;
+ Bool extracted;
+} GF_WidgetPackageResource;
+
+typedef struct _widget_package_relocator
+{
+ GF_TERM_URI_RELOCATOR
+ GF_List *resources;
+ struct _widget *widget;
+ GF_WidgetManager *wm;
+ Bool is_zip;
+ char root_extracted_path[GF_MAX_PATH];
+ char archive_id[14];
+ char *package_path;
+ GF_DownloadSession *sess;
+} GF_WidgetPackage;
+
+
+enum
+{
+ GF_WM_PARAM_OUTPUT,
+ GF_WM_PARAM_INPUT,
+ GF_WM_INPUT_ACTION,
+ GF_WM_OUTPUT_TRIGGER,
+ GF_WM_BIND_ACTION,
+ GF_WM_UNBIND_ACTION,
+ GF_WM_PREF_CONNECT,
+ GF_WM_ACTIVATE_TRIGGER,
+ GF_WM_DEACTIVATE_TRIGGER,
+ GF_WM_PREF_SAVEDACTION,
+ GF_WM_PREF_RESTOREDACTION,
+ GF_WM_PREF_SAVETRIGGER,
+ GF_WM_PREF_RESTORETRIGGER,
+};
+
+#define GF_WM_PARAM_SCRIPT_STRING (u16) 0
+#define GF_WM_PARAM_SCRIPT_BOOL (u16) 1
+#define GF_WM_PARAM_SCRIPT_NUMBER (u16) 2
+
+typedef struct
+{
+ struct __widget_message *msg;
+
+ u16 type;
+ u16 script_type;
+ Bool in_action;
+
+ char *name;
+ char *node;
+ char *attribute;
+ char *default_value;
+} GF_WidgetPin;
+
+typedef struct __widget_message
+{
+ struct _widget_interface *ifce;
+
+ char *name;
+ Bool is_output;
+ GF_List *params;
+
+ GF_WidgetPin *input_action;
+ GF_WidgetPin *output_trigger;
+
+} GF_WidgetMessage;
+
+typedef struct _widget_interface
+{
+ struct __widget_content *content;
+ char *type;
+ GF_List *messages;
+
+ GF_WidgetPin *bind_action;
+ GF_WidgetPin *unbind_action;
+ Bool provider, multiple_binding, required;
+ char *connectTo;
+
+ JSObject *obj;
+} GF_WidgetInterface;
+
+typedef struct _widget_component
+{
+ struct __widget_content *content;
+ char *id; /*may be NULL*/
+ char *src; /*may be NULL*/
+ GF_List *required_interfaces; /*may be empty*/
+ GF_WidgetPin *activateTrigger;
+ GF_WidgetPin *deactivateTrigger;
+ GF_WidgetPin *activatedAction;
+ GF_WidgetPin *deactivatedAction;
+} GF_WidgetComponent;
+
+enum
+{
+ GF_WM_PREF_READONLY = 1,
+ GF_WM_PREF_SAVE = 1<<1,
+ GF_WM_PREF_MIGRATE = 1<<2,
+};
+
+typedef struct
+{
+ char *name, *value;
+ u32 flags;
+ GF_WidgetPin *connectTo;
+} GF_WidgetPreference;
+
+typedef struct
+{
+ char *name, *value;
+} GF_WidgetFeatureParam;
+
+typedef struct
+{
+ char *name;
+ Bool required;
+ GF_List *params;
+} GF_WidgetFeature;
+
+typedef struct __widget_content
+{
+ struct _widget *widget;
+
+ char *src;
+ char *relocated_src;
+ u32 width, height;
+
+ char *encoding, *mimetype;
+
+ GF_List *interfaces;
+ GF_List *components;
+ /*list of preferences for the widget content*/
+ GF_List *preferences;
+
+ GF_WidgetPin *savedAction;
+ GF_WidgetPin *restoredAction;
+ GF_WidgetPin *saveTrigger;
+ GF_WidgetPin *restoreTrigger;
+} GF_WidgetContent;
+
+typedef struct _widget
+{
+ GF_WidgetManager *wm;
+
+ u32 nb_instances;
+
+ /* url to the file.wgt file when zip packaged or to the config.xml file when unpackaged */
+ char *url;
+ /* path to the manifest/config document */
+ char *manifest_path;
+
+ GF_List *icons;
+/*
+ GF_WidgetContent *simple;
+ char *icon_url;
+*/
+ GF_WidgetContent *main;
+
+ GF_WidgetPackage *wpack;
+
+ /*misc metadata for W3C Widgets API*/
+ char *name, *shortname, *identifier,
+ *authorName, *authorEmail, *authorHref,
+ *description, *version,
+ *uuid, *license, *licenseHref, *viewmodes;
+
+ u32 width, height;
+
+ GF_List *features;
+
+ Bool discardable, multipleInstance;
+
+ /*when a widget is being received from a remote peer,
+ we remember where we locally store it to be able to further remote it
+ This is only supported for packaged widgets*/
+ char *local_path;
+} GF_Widget;
+
+typedef struct _widget_instance
+{
+ GF_Widget *widget;
+
+ u32 instance_id;
+ JSObject *obj;
+ u8 secname[18];
+ GF_SceneGraph *scene;
+ /*node in the widget manager which holds the widget: Inline {} , <animation>, ...*/
+ GF_Node *anchor;
+
+ Bool activated, permanent;
+
+ GF_List *output_triggers;
+ GF_List *bound_ifces;
+ /*list of components for a parent widget*/
+ GF_List *components;
+ /*parent of the widget for a component widget*/
+ struct _widget_instance *parent;
+
+ GF_DOMParser *mpegu_context;
+
+
+ /*scripting context of the widget scene*/
+ JSContext *scene_context;
+ JSObject *scene_global;
+ /*"Widget" object in the scene*/
+ JSObject *scene_obj;
+} GF_WidgetInstance;
+
+
+typedef struct
+{
+ GF_WidgetInterface *ifce;
+ GF_WidgetInstance *wid;
+ char *hostname;
+ JSObject *obj;
+ JSObject *cookie;
+} GF_WidgetInterfaceInstance;
+
+typedef struct
+{
+ GF_WidgetComponent *comp;
+ GF_WidgetInstance *wid;
+} GF_WidgetComponentInstance;
+
+
+GF_WidgetInstance *wm_load_widget(GF_WidgetManager *wm, const char *path, u32 InstanceID, Bool skip_context);
+
+
+JSBool SMJS_FUNCTION(widget_has_feature);
+JSBool SMJS_FUNCTION(widget_open_url);
+JSBool SMJS_FUNCTION(widget_get_attention);
+JSBool SMJS_FUNCTION(widget_show_notification);
+JSBool SMJS_FUNCTION(widget_get_interface);
+JSBool widget_getProperty(JSContext *c, JSObject *obj, SMJS_PROP_GETTER, jsval *vp);
+JSBool widget_setProperty(JSContext *c, JSObject *obj, SMJS_PROP_SETTER, jsval *vp);
+
+void widget_on_interface_bind(GF_WidgetInterfaceInstance *ifce, Bool unbind);
+
+void widget_load(GF_WidgetManager *wm, GF_SceneGraph *scene, JSContext *c, JSObject *global, Bool unload);
+
+GF_WidgetComponentInstance *wm_activate_component(JSContext *c, GF_WidgetInstance *wid, GF_WidgetComponent *comp, Bool skip_wm_notification);
+
+void wm_deactivate_component(JSContext *c, GF_WidgetInstance *wid, GF_WidgetComponent *comp, GF_WidgetComponentInstance *comp_inst);
+
+
+
+const char *wm_xml_get_attr(GF_XMLNode *root, const char *name);
+
+GF_BaseInterface *LoadWidgetReader();
+void ShutdownWidgetReader(GF_BaseInterface *ifce);
+
+
+#endif /*GPAC_HAS_SPIDERMONKEY*/
+
+#endif
endif
CFLAGS+=-I"$(SRC_PATH)/include"
-# -I/usr/local/arm/3.3.2/include
ifeq ($(X11_INC_PATH), )
$(LIB): $(OBJS)
- $(CC) $(SHFLAGS) $(LDFLAGS) -lX11 -L../../bin/gcc -lgpac -o ../../bin/gcc/$@ $(OBJS) $(EXTRALIBS)
+ $(CC) $(SHFLAGS) $(LDFLAGS) -o ../../bin/gcc/$@ $(OBJS) -lX11 -L../../bin/gcc -lgpac $(EXTRALIBS)
ifeq ($(STATICBUILD),yes)
$(CC) $(SHFLAGS) $(LDFLAGS) -o ../../bin/gcc/gm_x11_out-static.$(DYN_LIB_SUFFIX) $(OBJS) -lX11 -L../../bin/gcc -lgpac_static $(EXTRALIBS)
endif
EXTRALIBS+=$(GPAC_SH_FLAGS)
endif
-LD_SONAME="-Wl,-soname,$(LIB)"
+LD_SONAME="-Wl,-soname,libgpac.so.$(VERSION_MAJOR)"
ifeq ($(CONFIG_DARWIN), yes)
LD_SONAME=
endif
ar cr ../bin/gcc/libgpac_static.a $(OBJS)
ranlib ../bin/gcc/libgpac_static.a
$(CC) $(SHFLAGS) $(LD_SONAME) $(LDFLAGS) -o ../bin/gcc/$@ $(OBJS) $(EXTRALIBS)
+ifeq (,$(findstring yes, $(CONFIG_WIN32)))
+ mv ../bin/gcc/$@ ../bin/gcc/$@.$(VERSION_SONAME)
+ ln -sf $@.$(VERSION_SONAME) ../bin/gcc/$@.$(VERSION_MAJOR)
+ ln -sf $@.$(VERSION_SONAME) ../bin/gcc/$@
+endif
endif
dep: depend
clean:
rm -f $(OBJS) ../bin/gcc/$(LIB)
- rm -rf ../bin/gcc/libgpac_static.a
+ rm -rf ../bin/gcc/libgpac_static.a ../bin/gcc/libgpac.so \
+ ../bin/gcc/libgpac.so.$(VERSION_MAJOR) \
+ ../bin/gcc/libgpac.so.$(VERSION_SONAME)
distclean: clean
rm -f Makefile.bak .depend
};
GF_Err SFScript_Parse(GF_BifsDecoder *codec, SFScript *script_field, GF_BitStream *bs, GF_Node *n);
+#ifndef GPAC_DISABLE_BIFS_ENC
GF_Err SFScript_Encode(GF_BifsEncoder *codec, SFScript *script_field, GF_BitStream *bs, GF_Node *n);
+#endif
#endif /* !defined(GPAC_DISABLE_BIFS) && defined(GPAC_HAS_SPIDERMONKEY) */
#include <gpac/internal/scenegraph_dev.h>
-#if !defined(GPAC_DISABLE_BIFS) && defined(GPAC_HAS_SPIDERMONKEY)
+#if !defined(GPAC_DISABLE_BIFS) && !defined(GPAC_DISABLE_BIFS_ENC) && defined(GPAC_HAS_SPIDERMONKEY)
typedef struct
{
}
}
-#endif /* !defined(GPAC_DISABLE_BIFS) && defined(GPAC_HAS_SPIDERMONKEY) */
+#endif /* !defined(GPAC_DISABLE_BIFS) && !defined(GPAC_DISABLE_BIFS_ENC) && defined(GPAC_HAS_SPIDERMONKEY) */
new_tag = TAG_MPEG4_Layer3D;
}
}
-#ifndef GPAC_DISABLE_3D
+#if !defined(GPAC_DISABLE_X3D) && !defined(GPAC_DISABLE_3D)
/*if the inlined root node is a 3D one except Layer3D and we are not in a 3D context, insert
a Layer3D at the root*/
else if (!tr_state->visual->type_3d && ((tag==TAG_MPEG4_Group) || (tag==TAG_X3D_Group))) {
}
}
-#ifndef GPAC_DISABLE_VRML
+#if !defined(GPAC_DISABLE_VRML) && !defined(GPAC_DISABLE_X3D)
void mesh_generate_tex_coords(GF_Mesh *mesh, GF_Node *__texCoords)
{
u32 i;
{
u32 i, n, count, c_count, col_count;
u32 index;
- u32 first_idx, last_idx;
+ u32 first_idx, last_idx;
Bool move_to;
SFVec3f pt;
SFColorRGBA colRGBA;
M_Coordinate2D *coord2D = (M_Coordinate2D*) __coord;
M_Coordinate *coord = (M_Coordinate*) __coord;
M_Color *colorRGB = (M_Color *) __color;
+#ifndef GPAC_DISABLE_X3D
X_ColorRGBA *colorRGBA = (X_ColorRGBA *) __color;
+#endif
if (__coord && (gf_node_get_tag(__coord) == TAG_MPEG4_Coordinate2D)) {
coord = NULL;
}
has_color = 0;
if (__color) {
+#ifndef GPAC_DISABLE_X3D
if (gf_node_get_tag(__color)==TAG_X3D_ColorRGBA) {
colorRGB = NULL;
has_color = (colorRGBA->color.count) ? 1 : 0;
- } else {
- colorRGBA = NULL;
+ } else
+#endif
+ {
+#ifndef GPAC_DISABLE_X3D
+ colorRGBA = NULL;
+#endif
has_color = (colorRGB->color.count) ? 1 : 0;
}
}
n = 0;
if (has_color && !colorPerVertex) {
index = colorIndex->count ? colorIndex->vals[0] : 0;
+#ifndef GPAC_DISABLE_X3D
if ((u32) index < col_count) MESH_GET_COL(colRGBA, index);
+#endif
}
move_to = 1;
if (n<colorIndex->count) index = colorIndex->vals[n];
else if (n<col_count) index = n;
else index = 0;
+#ifndef GPAC_DISABLE_X3D
MESH_GET_COL(colRGBA, index);
+#endif
}
} else {
if (has_color && colorPerVertex) {
if (i<colorIndex->count) index = colorIndex->vals[i];
else if (i<col_count) index = i;
else index=0;
+#ifndef GPAC_DISABLE_X3D
MESH_GET_COL(colRGBA, index);
+#endif
}
if (has_coord) index = coordIndex->vals[i];
else index = i;
mesh_set_line(mesh, last_idx, first_idx);
}
if (coord2D) mesh->flags |= MESH_IS_2D;
+#ifndef GPAC_DISABLE_X3D
if (colorRGBA) mesh->flags |= MESH_HAS_ALPHA;
+#endif
mesh_update_bounds(mesh);
}
M_Coordinate2D *coord2D = (M_Coordinate2D*) __coord;
M_Coordinate *coord = (M_Coordinate*) __coord;
M_Color *colorRGB = (M_Color *) __color;
+#ifndef GPAC_DISABLE_X3D
X_ColorRGBA *colorRGBA = (X_ColorRGBA *) __color;
+#endif
if (__coord && (gf_node_get_tag(__coord) == TAG_MPEG4_Coordinate2D)) {
coord = NULL;
has_color = 0;
if (__color) {
+#ifndef GPAC_DISABLE_X3D
if (gf_node_get_tag(__color)==TAG_X3D_ColorRGBA) {
colorRGB = NULL;
has_color = (colorRGBA->color.count) ? 1 : 0;
- } else {
+ } else
+#endif
+ {
+#ifndef GPAC_DISABLE_X3D
colorRGBA = NULL;
+#endif
has_color = (colorRGB->color.count) ? 1 : 0;
}
}
colRGBA.red = colRGBA.green = colRGBA.blue = colRGBA.alpha = FIX_ONE;
for (i=0; i<c_count; ++i) {
+#ifndef GPAC_DISABLE_X3D
if (has_color) MESH_GET_COL(colRGBA, i);
+#endif
if (coord2D) {
pt.x = coord2D->point.vals[i].x;
pt.y = coord2D->point.vals[i].y;
M_Coordinate2D *coord2D = (M_Coordinate2D*) __coord;
M_Coordinate *coord = (M_Coordinate*) __coord;
M_Color *colorRGB = (M_Color *) __color;
+#ifndef GPAC_DISABLE_X3D
X_ColorRGBA *colorRGBA = (X_ColorRGBA *) __color;
+#endif
M_Normal *normal = (M_Normal*) __normal;
M_TextureCoordinate *txcoord = (M_TextureCoordinate*) __texCoords;
coord = NULL;
} else {
coord2D = NULL;
- if (!__coord) return;
+ if (!__coord)
+ return;
/*not supported yet*/
- if (gf_node_get_tag(__coord) == TAG_X3D_CoordinateDouble) return;
+#ifndef GPAC_DISABLE_X3D
+ if (gf_node_get_tag(__coord) == TAG_X3D_CoordinateDouble)
+ return;
+#endif
}
gen_tex_coords = 0;
+#ifndef GPAC_DISABLE_X3D
if (__texCoords && (gf_node_get_tag(__texCoords)==TAG_X3D_TextureCoordinateGenerator)) {
gen_tex_coords = 1;
txcoord = NULL;
}
+#endif
if (!coord2D && !coord) return;
c_count = coord2D ? coord2D->point.count : coord->point.count;
has_color = 0;
if (__color) {
+#ifndef GPAC_DISABLE_X3D
if (gf_node_get_tag(__color)==TAG_X3D_ColorRGBA) {
colorRGB = NULL;
has_color = (colorRGBA->color.count) ? 1 : 0;
- } else {
+ } else
+#endif
+ {
+#ifndef GPAC_DISABLE_X3D
colorRGBA = NULL;
+#endif
has_color = (colorRGB->color.count) ? 1 : 0;
}
}
if (has_color) {
if (!colorPerVertex) {
index = colorIndex->count ? colorIndex->vals[0] : 0;
+#ifndef GPAC_DISABLE_X3D
MESH_GET_COL(colRGBA, index);
+#endif
} else {
if (!colorIndex->vals) colorIndex = coordIndex;
}
n++;
if (has_color && !colorPerVertex) {
GET_IDX(n, colorIndex);
+#ifndef GPAC_DISABLE_X3D
MESH_GET_COL(colRGBA, index);
+#endif
}
if (has_normal && !normalPerVertex) {
GET_IDX(n, normalIndex);
} else {
if (has_color && colorPerVertex) {
GET_IDX(i, colorIndex);
+#ifndef GPAC_DISABLE_X3D
MESH_GET_COL(colRGBA, index);
+#endif
}
if (has_normal && normalPerVertex) {
GET_IDX(i, normalIndex);
if (!coord2D) gf_mesh_build_aabbtree(mesh);
+#ifndef GPAC_DISABLE_X3D
if (colorRGBA) mesh->flags |= MESH_HAS_ALPHA;
if (gen_tex_coords) mesh_generate_tex_coords(mesh, __texCoords);
+#endif
}
void mesh_new_ifs2d(GF_Mesh *mesh, GF_Node *node)
M_ElevationGrid *eg = (M_ElevationGrid *) node;
M_Normal *norm = (M_Normal *)eg->normal;
M_Color *colorRGB = (M_Color *)eg->color;
+#ifndef GPAC_DISABLE_X3D
X_ColorRGBA *colorRGBA = (X_ColorRGBA *)eg->color;
+#endif
SFColorRGBA rgba;
M_TextureCoordinate *txc = (M_TextureCoordinate *)eg->texCoord;
has_normal = norm ? norm->vector.count : 0;
has_color = 0;
if (eg->color) {
+#ifndef GPAC_DISABLE_X3D
if (gf_node_get_tag(eg->color)==TAG_X3D_ColorRGBA) {
colorRGB = NULL;
has_color = colorRGBA->color.count ? 1 : 0;
- } else {
+ } else
+#endif
+ {
+#ifndef GPAC_DISABLE_X3D
colorRGBA = NULL;
+#endif
has_color = colorRGB->color.count ? 1 : 0;
}
}
/*get face color*/
if (has_color && !eg->colorPerVertex) {
idx = i + j * (xDimension-1);
+#ifndef GPAC_DISABLE_X3D
MESH_GET_COL(rgba, idx);
+#endif
vx.color = MESH_MAKE_COL(rgba);
}
/*get face normal*/
/*get color per vertex*/
if (has_color && eg->colorPerVertex) {
idx = i+l + (j+k) * xDimension;
+#ifndef GPAC_DISABLE_X3D
MESH_GET_COL(rgba, idx);
+#endif
vx.color = MESH_MAKE_COL(rgba);
}
/*get tex coord*/
mesh_update_bounds(mesh);
if (!eg->ccw) mesh->flags |= MESH_IS_CW;
if (eg->solid) mesh->flags |= MESH_IS_SOLID;
+#ifndef GPAC_DISABLE_X3D
if (colorRGBA) mesh->flags |= MESH_HAS_ALPHA;
+#endif
gf_mesh_build_aabbtree(mesh);
}
#pragma comment (linker, EXPORT_SYMBOL(gf_media_make_psp) )
#pragma comment (linker, EXPORT_SYMBOL(gf_media_import) )
#pragma comment (linker, EXPORT_SYMBOL(gf_media_import_chapters) )
-#pragma comment (linker, EXPORT_SYMBOL(gf_media_change_par) )
#pragma comment (linker, EXPORT_SYMBOL(gf_media_change_pl) )
-#pragma comment (linker, EXPORT_SYMBOL(gf_media_fragment_file) )
#pragma comment (linker, EXPORT_SYMBOL(gf_media_avc_rewrite_samples) )
#endif /*GPAC_DISABLE_MEDIA_IMPORT*/
+#pragma comment (linker, EXPORT_SYMBOL(gf_media_change_par) )
+
#ifndef GPAC_DISABLE_AV_PARSERS
#pragma comment (linker, EXPORT_SYMBOL(gf_avc_get_sps_info) )
#pragma comment (linker, EXPORT_SYMBOL(gf_sm_load_bt_from_string) )
#endif
-#ifndef GPAC_DISABLE_SCENE_ENCODER
+#if !defined(GPAC_DISABLE_SCENE_ENCODER) && !defined(GPAC_DISABLE_ISOM_WRITE)
#pragma comment (linker, EXPORT_SYMBOL(gf_sm_encode_to_file) )
#endif
#pragma comment (linker, EXPORT_SYMBOL(gf_sm_dump) )
#pragma comment (linker, EXPORT_SYMBOL(gf_sm_dump_command_list) )
#pragma comment (linker, EXPORT_SYMBOL(gf_sm_dump_graph) )
+#ifndef GPAC_DISABLE_OD_DUMP
#pragma comment (linker, EXPORT_SYMBOL(gf_odf_dump_au) )
#pragma comment (linker, EXPORT_SYMBOL(gf_odf_dump_com) )
#pragma comment (linker, EXPORT_SYMBOL(gf_odf_dump_desc) )
#pragma comment (linker, EXPORT_SYMBOL(gf_odf_dump_com_list) )
+#ifndef GPAC_MINIMAL_ODF
#pragma comment (linker, EXPORT_SYMBOL(gf_oci_dump_event) )
#pragma comment (linker, EXPORT_SYMBOL(gf_oci_dump_au) )
#endif
+#endif
+#endif
#ifndef GPAC_DISABLE_SENG
/*bifsengine exports*/
#pragma comment (linker, EXPORT_SYMBOL(gf_dm_wget) )
#pragma comment (linker, EXPORT_SYMBOL(gf_dm_wget_with_cache) )
-#ifndef GPAC_DISABLE_ISOM
+#ifndef GPAC_DISABLE_ISOM_WRITE
#pragma comment (linker, EXPORT_SYMBOL(gf_media_mpd_start) )
#pragma comment (linker, EXPORT_SYMBOL(gf_media_mpd_end) )
+#ifndef GPAC_DISABLE_ISOM_FRAGMENTS
+#pragma comment (linker, EXPORT_SYMBOL(gf_media_fragment_file) )
+#endif
#endif
/* dvb_mpe.h */
#endif
#include <gpac/internal/ietf_dev.h>
-#ifndef GPAC_DISABLE_STREAMING
+#if !defined(GPAC_DISABLE_STREAMING) && !defined(GPAC_DISABLE_ISOM)
struct __rtp_streamer
{
return gf_rtp_send_rtcp_report(streamer->channel, NULL, NULL);
}
-#endif /*GPAC_DISABLE_STREAMING*/
+#endif /*GPAC_DISABLE_STREAMING && GPAC_DISABLE_ISOM*/
return GF_OK;
}
-
-
#endif /*GPAC_DISABLE_ISOM_WRITE*/
#endif /*GPAC_DISABLE_ISOM_FRAGMENTS*/
+
void tims_del(GF_Box *s)
{
GF_TSHintEntryBox *tims = (GF_TSHintEntryBox *)s;
return (GF_Box *)tmp;
}
-
#ifndef GPAC_DISABLE_ISOM_WRITE
-
GF_Err traf_Write(GF_Box *s, GF_BitStream *bs)
{
GF_Err e;
#endif /*GPAC_DISABLE_ISOM_WRITE*/
-#ifndef GPAC_DISABLE_ISOM_FRAGMENTS
void sidx_del(GF_Box *s)
{
#endif /*GPAC_DISABLE_ISOM_WRITE*/
-#endif /*GPAC_DISABLE_ISOM_FRAGMENTS*/
GF_Box *subs_New()
gf_free(ptr);
}
+
+#ifndef GPAC_DISABLE_ISOM_WRITE
+
GF_Err subs_Write(GF_Box *s, GF_BitStream *bs)
{
GF_Err e;
return GF_OK;
}
+#endif /*GPAC_DISABLE_ISOM_WRITE*/
GF_Err subs_Read(GF_Box *s, GF_BitStream *bs)
{
}
+#ifndef GPAC_DISABLE_ISOM_FRAGMENTS
+
GF_Box *tfdt_New()
{
GF_TFBaseMediaDecodeTimeBox *tmp;
#endif /*GPAC_DISABLE_ISOM_WRITE*/
-
+#endif /*GPAC_DISABLE_ISOM_FRAGMENTS*/
GF_Box *rvcc_New()
return GF_OK;
}
+
GF_Err sidx_dump(GF_Box *a, FILE * trace)
{
u32 i;
return GF_OK;
}
-
+#ifndef GPAC_DISABLE_ISOM_FRAGMENTS
GF_Err tfdt_dump(GF_Box *a, FILE * trace)
{
GF_TFBaseMediaDecodeTimeBox *ptr = (GF_TFBaseMediaDecodeTimeBox*) a;
fprintf(trace, "</TrackFragmentBaseMediaDecodeTimeBox>\n");
return GF_OK;
}
+#endif /*GPAC_DISABLE_ISOM_FRAGMENTS*/
GF_Err rvcc_dump(GF_Box *a, FILE * trace)
{
case GF_ISOM_BOX_TYPE_LSRC: return lsrc_New();
case GF_ISOM_BOX_TYPE_LSR1: return lsr1_New();
+#ifndef GPAC_DISABLE_ISOM_FRAGMENTS
case GF_ISOM_BOX_TYPE_SIDX: return sidx_New();
case GF_ISOM_BOX_TYPE_SUBS: return subs_New();
case GF_ISOM_BOX_TYPE_TFDT: return tfdt_New();
+#endif
case GF_ISOM_BOX_TYPE_RVCC: return rvcc_New();
default:
case GF_ISOM_BOX_TYPE_MFHD: mfhd_del(a); return;
case GF_ISOM_BOX_TYPE_TRAF: traf_del(a); return;
case GF_ISOM_BOX_TYPE_TFHD: tfhd_del(a); return;
+ case GF_ISOM_BOX_TYPE_TFDT: tfdt_del(a); return;
case GF_ISOM_BOX_TYPE_TRUN: trun_del(a); return;
#endif
case GF_ISOM_BOX_TYPE_SIDX: sidx_del(a); return;
case GF_ISOM_BOX_TYPE_SUBS: subs_del(a); return;
- case GF_ISOM_BOX_TYPE_TFDT: tfdt_del(a); return;
case GF_ISOM_BOX_TYPE_RVCC: rvcc_del(a); return;
default:
}
-
-
GF_Err gf_isom_box_read(GF_Box *a, GF_BitStream *bs)
{
switch (a->type) {
case GF_ISOM_BOX_TYPE_MFHD: return mfhd_Read(a, bs);
case GF_ISOM_BOX_TYPE_TRAF: return traf_Read(a, bs);
case GF_ISOM_BOX_TYPE_TFHD: return tfhd_Read(a, bs);
+ case GF_ISOM_BOX_TYPE_TFDT: return tfdt_Read(a, bs);
case GF_ISOM_BOX_TYPE_TRUN: return trun_Read(a, bs);
#endif
case GF_ISOM_BOX_TYPE_SIDX: return sidx_Read(a, bs);
case GF_ISOM_BOX_TYPE_SUBS: return subs_Read(a, bs);
- case GF_ISOM_BOX_TYPE_TFDT: return tfdt_Read(a, bs);
case GF_ISOM_BOX_TYPE_RVCC: return rvcc_Read(a, bs);
default:
case GF_ISOM_BOX_TYPE_MFHD: return mfhd_Write(a, bs);
case GF_ISOM_BOX_TYPE_TRAF: return traf_Write(a, bs);
case GF_ISOM_BOX_TYPE_TFHD: return tfhd_Write(a, bs);
+ case GF_ISOM_BOX_TYPE_TFDT: return tfdt_Write(a, bs);
case GF_ISOM_BOX_TYPE_TRUN: return trun_Write(a, bs);
#endif
case GF_ISOM_BOX_TYPE_SIDX: return sidx_Write(a, bs);
case GF_ISOM_BOX_TYPE_SUBS: return subs_Write(a, bs);
- case GF_ISOM_BOX_TYPE_TFDT: return tfdt_Write(a, bs);
case GF_ISOM_BOX_TYPE_RVCC: return rvcc_Write(a, bs);
default:
case GF_ISOM_BOX_TYPE_MFHD: return mfhd_Size(a);
case GF_ISOM_BOX_TYPE_TRAF: return traf_Size(a);
case GF_ISOM_BOX_TYPE_TFHD: return tfhd_Size(a);
+ case GF_ISOM_BOX_TYPE_TFDT: return tfdt_Size(a);
case GF_ISOM_BOX_TYPE_TRUN: return trun_Size(a);
#endif
case GF_ISOM_BOX_TYPE_SIDX: return sidx_Size(a);
case GF_ISOM_BOX_TYPE_SUBS: return subs_Size(a);
- case GF_ISOM_BOX_TYPE_TFDT: return tfdt_Size(a);
case GF_ISOM_BOX_TYPE_RVCC: return rvcc_Size(a);
default: return defa_Size(a);
#endif
gf_isom_box_array_del(mov->TopBoxes);
+#ifndef GPAC_DISABLE_ISOM_FRAGMENTS
gf_isom_box_array_del(mov->moof_list);
-
+#endif
if (mov->fileName) gf_free(mov->fileName);
gf_free(mov);
if (! trak->editBox || !trak->editBox->editList) {
*MediaTime = movieTime;
//check this is in our media time line
- if (!trak->moov->mov->use_segments && (*MediaTime > lastSampleTime)) *MediaTime = lastSampleTime;
+ if ((*MediaTime > lastSampleTime)
+#ifndef GPAC_DISABLE_ISOM_FRAGMENTS
+ && !trak->moov->mov->use_segments
+#endif
+ ) {
+ *MediaTime = lastSampleTime;
+ }
*useEdit = 0;
return GF_OK;
}
{
if (!the_file) return 0;
if (the_file->movieFileMap) return gf_bs_get_size(the_file->movieFileMap->bs);
+#ifndef GPAC_DISABLE_ISOM_WRITE
if (the_file->editFileMap) return gf_bs_get_size(the_file->editFileMap->bs);
+#endif
return 0;
}
GF_TrackBox *trak;
trak = gf_isom_get_track_from_file(the_file, trackNumber);
if (!trak) return 0;
- return trak->Media->information->sampleTable->SampleSize->sampleCount + trak->sample_count_at_seg_start;
+ return trak->Media->information->sampleTable->SampleSize->sampleCount
+#ifndef GPAC_DISABLE_ISOM_FRAGMENTS
+ + trak->sample_count_at_seg_start
+#endif
+ ;
}
u32 gf_isom_get_constant_sample_size(GF_ISOFile *the_file, u32 trackNumber)
return GF_EOS;
}
}
- else if (!trak->dts_at_seg_start && (movieTime * trak->moov->mvhd->timeScale > trak->Header->duration * trak->Media->mediaHeader->timeScale)) {
+ else if ((movieTime * trak->moov->mvhd->timeScale > trak->Header->duration * trak->Media->mediaHeader->timeScale)
+#ifndef GPAC_DISABLE_ISOM_FRAGMENTS
+ && !trak->dts_at_seg_start
+#endif
+ ) {
*sample = NULL;
if (sampleNumber) *sampleNumber = 0;
*StreamDescriptionIndex = 0;
if (!movie) return;
for (i=0; i<gf_list_count(movie->moov->trackList); i++) {
GF_TrackBox *trak = gf_list_get(movie->moov->trackList, i);
+ trak->Media->information->sampleTable->SampleSize->sampleCount = 0;
+#ifdef GPAC_DISABLE_ISOM_FRAGMENTS
+ }
+#else
trak->dts_at_seg_start = 0;
trak->sample_count_at_seg_start = 0;
- trak->Media->information->sampleTable->SampleSize->sampleCount = 0;
}
movie->NextMoofNumber = 0;
+#endif
}
GF_Err gf_isom_get_sample_rap_roll_info(GF_ISOFile *the_file, u32 trackNumber, u32 sample_number, Bool *is_rap, Bool *has_roll, s32 *roll_distance)
GF_Err gf_isom_set_brand_info(GF_ISOFile *movie, u32 MajorBrand, u32 MinorVersion)
{
u32 i, *p;
- GF_Err e;
if (!MajorBrand) return GF_BAD_PARAM;
+#ifndef GPAC_DISABLE_ISOM_FRAGMENTS
if (! (movie->FragmentsFlags & GF_ISOM_FRAG_WRITE_READY)) {
- e = CanAccessMovie(movie, GF_ISOM_OPEN_WRITE);
+ GF_Err e = CanAccessMovie(movie, GF_ISOM_OPEN_WRITE);
if (e) return e;
e = CheckNoData(movie);
if (e) return e;
}
+#endif
if (!movie->brand) {
movie->brand = (GF_FileTypeBox *) gf_isom_box_new(GF_ISOM_BOX_TYPE_FTYP);
GF_Err gf_isom_modify_alternate_brand(GF_ISOFile *movie, u32 Brand, u8 AddIt)
{
u32 i, k, *p;
- GF_Err e;
if (!Brand) return GF_BAD_PARAM;
+#ifndef GPAC_DISABLE_ISOM_FRAGMENTS
if (! (movie->FragmentsFlags & GF_ISOM_FRAG_WRITE_READY)) {
- e = CanAccessMovie(movie, GF_ISOM_OPEN_WRITE);
+ GF_Err e = CanAccessMovie(movie, GF_ISOM_OPEN_WRITE);
if (e) return e;
e = CheckNoData(movie);
if (e) return e;
}
+#endif
if (!movie->brand && AddIt) {
movie->brand = (GF_FileTypeBox *) gf_isom_box_new(GF_ISOM_BOX_TYPE_FTYP);
GF_Err gf_isom_reset_alt_brands(GF_ISOFile *movie)
{
u32 *p;
- GF_Err e;
+#ifndef GPAC_DISABLE_ISOM_FRAGMENTS
if (! (movie->FragmentsFlags & GF_ISOM_FRAG_WRITE_READY)) {
- e = CanAccessMovie(movie, GF_ISOM_OPEN_WRITE);
+ GF_Err e = CanAccessMovie(movie, GF_ISOM_OPEN_WRITE);
if (e) return e;
e = CheckNoData(movie);
if (e) return e;
}
+#endif
if (!movie->brand) {
movie->brand = (GF_FileTypeBox *) gf_isom_box_new(GF_ISOM_BOX_TYPE_FTYP);
return NULL;
}
-
-#ifndef GPAC_DISABLE_ISOM_WRITE
-
GF_TrackFragmentBox *GetTraf(GF_ISOFile *mov, u32 TrackID)
{
u32 i;
return NULL;
}
+
+#ifndef GPAC_DISABLE_ISOM_WRITE
+
GF_Err gf_isom_finalize_for_fragment(GF_ISOFile *movie, Bool use_segments)
{
GF_Err e;
*
*/
-#include <gpac/isomedia.h>
-#include <gpac/ietf.h>
-#include <gpac/config_file.h>
-#include <gpac/base_coding.h>
#include <gpac/internal/media_dev.h>
-#include <gpac/filestreamer.h>
-#include <gpac/rtp_streamer.h>
#include <gpac/constants.h>
#include <gpac/math.h>
#if !defined(GPAC_DISABLE_ISOM) && !defined(GPAC_DISABLE_STREAMING)
+#include <gpac/isomedia.h>
+#include <gpac/ietf.h>
+#include <gpac/config_file.h>
+#include <gpac/base_coding.h>
+#include <gpac/filestreamer.h>
+#include <gpac/rtp_streamer.h>
typedef struct __tag_rtp_track
{
GF_IPMPPtr *ipmpdp;
GF_IPMP_Descriptor *ipmpd;
GF_IPMPUpdate *ipmpdU;
+#ifndef GPAC_MINIMAL_ODF
GF_IPMPX_ISMACryp *ismac;
+#endif
GF_Err e;
Bool prev_sample_encryped, has_crypted_samp;
/*format IPMPD*/
ipmpd = (GF_IPMP_Descriptor*)gf_odf_desc_new(GF_ODF_IPMP_TAG);
if (tci->ipmp_type==2) {
+#ifndef GPAC_MINIMAL_ODF
ipmpd->IPMP_DescriptorID = 0xFF;
ipmpd->IPMP_DescriptorIDEx = tci->ipmp_desc_id;
ipmpd->IPMPS_Type = 0xFFFF;
ismac->key_indicator_length = 0;
ismac->use_selective_encryption = (tci->sel_enc_type!=0)? 1 : 0;
gf_list_add(ipmpd->ipmpx_data, ismac);
+#endif
} else {
ipmpd->IPMP_DescriptorID = tci->ipmp_desc_id;
}
}
break;
case GF_STREAM_VISUAL:
+#ifndef GPAC_DISABLE_AV_PARSERS
if (esd->decoderConfig->decoderSpecificInfo) {
GF_M4VDecSpecInfo dsi;
gf_m4v_get_config(esd->decoderConfig->decoderSpecificInfo->data, esd->decoderConfig->decoderSpecificInfo->dataLength, &dsi);
sprintf(szCodec, "mp4v.%02x.%02x", esd->decoderConfig->objectTypeIndication, dsi.VideoPL);
- } else {
+ } else
+#endif
+ {
sprintf(szCodec, "mp4v.%02x", esd->decoderConfig->objectTypeIndication);
}
break;
}
+#ifndef GPAC_DISABLE_ISOM_FRAGMENTS
+
GF_EXPORT
GF_Err gf_media_fragment_file(GF_ISOFile *input, const char *output_file, const char *mpd_name, Double max_duration_sec, u32 dash_mode, Double dash_duration_sec, char *seg_rad_name, char *seg_ext, s32 subsegs_per_sidx, Bool daisy_chain_sidx, Bool use_url_template, Bool single_segment_mode, const char *dash_ctx_file, GF_ISOFile *sample_descs, u32 rep_idx)
{
GF_Err e;
char sOpt[100], sKey[100];
char szCodecs[200], szCodec[100];
- char szComponents[1000];
u32 cur_seg, fragment_index, nb_fragments, max_sap_type;
GF_ISOFile *output;
GF_ISOSample *sample, *next;
}
+#ifndef GPAC_DISABLE_ISOM_FRAGMENTS
//the initialization segment is not yet setup for fragmentation
if (! gf_isom_is_track_fragmented(sample_descs, tf->TrackID)) {
e = gf_isom_setup_track_fragment(sample_descs, sample_descs_track,
e = gf_isom_change_track_fragment_defaults(output, TrackNum,
defaultDuration, defaultSize, defaultDescriptionIndex, defaultRandomAccess, defaultPadding, defaultDegradationPriority);
if (e) goto err_exit;
-
-
}
+#endif
/*reset all sample desc and clone with new ones*/
gf_isom_clone_sample_descriptions(output, TrackNum, sample_descs, sample_descs_track, 1);
nb_samp += count;
}
- /*format component info*/
- szComponents[0] = 0;
- for (i=0; i<gf_list_count(fragmenters); i++) {
- char szComponent[100];
- tf = gf_list_get(fragmenters, i);
- switch (tf->MediaType) {
- case GF_ISOM_MEDIA_TEXT:
- gf_isom_get_media_language(input, i+1, langCode);
- sprintf(szComponent, " <ContentComponent id=\"%d\" contentType=\"text\" lang=\"%s\"/>\n", tf->TrackID, langCode);
- break;
- case GF_ISOM_MEDIA_VISUAL:
- sprintf(szComponent, " <ContentComponent id=\"%d\" contentType=\"video\"/>\n", tf->TrackID);
- break;
- case GF_ISOM_MEDIA_SCENE:
- case GF_ISOM_MEDIA_DIMS:
- sprintf(szComponent, " <ContentComponent id=\"%d\" contentType=\"application\" lang=\"%s\"/>\n", tf->TrackID, langCode);
- break;
- case GF_ISOM_MEDIA_AUDIO:
- sprintf(szComponent, " <ContentComponent id=\"%d\" contentType=\"audio\" lang=\"%s\"/>\n", tf->TrackID, langCode);
- break;
- }
- strcat(szComponents, szComponent);
- }
-
if (!tfref) tfref = gf_list_get(fragmenters, 0);
tfref->is_ref_track = 1;
tfref_timescale = tfref->TimeScale;
if (tfref->all_sample_raps) split_seg_at_rap = 1;
//flush movie
+#ifndef GPAC_DISABLE_ISOM_FRAGMENTS
e = gf_isom_finalize_for_fragment(output, dash_mode ? 1 : 0);
if (e) goto err_exit;
+#endif
start_range = 0;
file_size = gf_isom_get_file_size(output);
fprintf(mpd, " bandwidth=\"%d\"", bandwidth);
fprintf(mpd, ">\n");
- if (strlen(szComponents)) fprintf(mpd, "%s", szComponents);
if (dash_ctx) {
Double seg_dur;
return e;
}
+#endif /*GPAC_DISABLE_ISOM_FRAGMENTS*/
-GF_Err gf_media_mpd_start(char *mpd_name, char *title, Bool use_url_template, Bool single_segment, char *dash_ctx, char *init_segment, Double period_duration)
+GF_Err gf_media_mpd_start(char *mpd_name, char *title, Bool use_url_template, Bool single_segment, char *dash_ctx, GF_ISOFile *init_segment, Double period_duration)
{
u32 h, m;
Double s;
fprintf(mpd, " <AdaptationSet>\n");
if (init_segment) {
+ u32 i;
+ char langCode[4];
+ langCode[3] = 0;
+
+ for (i=0; i<gf_isom_get_track_count(init_segment); i++) {
+ u32 trackID = gf_isom_get_track_id(init_segment, i+1);
+
+ gf_isom_get_media_language(init_segment, i+1, langCode);
+
+ switch (gf_isom_get_media_type(init_segment, i+1) ) {
+ case GF_ISOM_MEDIA_TEXT:
+ fprintf(mpd, " <ContentComponent id=\"%d\" contentType=\"text\" lang=\"%s\"/>\n", trackID, langCode);
+ break;
+ case GF_ISOM_MEDIA_VISUAL:
+ fprintf(mpd, " <ContentComponent id=\"%d\" contentType=\"video\"/>\n", trackID);
+ break;
+ case GF_ISOM_MEDIA_SCENE:
+ case GF_ISOM_MEDIA_DIMS:
+ fprintf(mpd, " <ContentComponent id=\"%d\" contentType=\"application\" lang=\"%s\"/>\n", trackID, langCode);
+ break;
+ case GF_ISOM_MEDIA_AUDIO:
+ fprintf(mpd, " <ContentComponent id=\"%d\" contentType=\"audio\" lang=\"%s\"/>\n", trackID, langCode);
+ break;
+ }
+ }
+
if (use_url_template) {
- fprintf(mpd, " <SegmentTemplate initialization=\"%s\"/>\n", init_segment);
+ fprintf(mpd, " <SegmentTemplate initialization=\"%s\"/>\n", gf_isom_get_filename(init_segment) );
} else if (0 && !single_segment) {
fprintf(mpd, " <SegmentList>\n");
- fprintf(mpd, " <Initialization sourceURL=\"%s\"/>\n", init_segment);
+ fprintf(mpd, " <Initialization sourceURL=\"%s\"/>\n", gf_isom_get_filename(init_segment) );
fprintf(mpd, " </SegmentList>\n");
}
}
#include <gpac/constants.h>
#include <gpac/media_tools.h>
-#ifndef GPAC_DISABLE_MPEG2TS_MUX
+#if !defined(GPAC_DISABLE_MPEG2TS_MUX) && !defined(GPAC_DISABLE_MPEG2TS)
/*num ms between PCR*/
#define PCR_UPDATE_MS 200
}
/*MPEG4*/
else {
+#ifndef GPAC_DISABLE_AV_PARSERS
/*ignore visual size info, get it from dsi*/
gf_m4v_get_config(esd->decoderConfig->decoderSpecificInfo->data, esd->decoderConfig->decoderSpecificInfo->dataLength, &dsi);
w = dsi.width;
h = dsi.height;
+#endif
v4CC = "XVID";
return gf_import_message(importer, e, "Unknown input file type");
}
+
+GF_EXPORT
+GF_Err gf_media_change_pl(GF_ISOFile *file, u32 track, u32 profile, u32 level)
+{
+ u32 i, count, stype;
+ GF_Err e;
+ GF_AVCConfig *avcc;
+
+ stype = gf_isom_get_media_subtype(file, track, 1);
+ switch (stype) {
+ case GF_ISOM_SUBTYPE_AVC_H264:
+ case GF_ISOM_SUBTYPE_AVC2_H264:
+ break;
+ default:
+ return GF_OK;
+ }
+
+ avcc = gf_isom_avc_config_get(file, track, 1);
+ if (level) avcc->AVCLevelIndication = level;
+ if (profile) avcc->AVCProfileIndication = profile;
+ count = gf_list_count(avcc->sequenceParameterSets);
+ for (i=0; i<count; i++) {
+ GF_AVCConfigSlot *slc = gf_list_get(avcc->sequenceParameterSets, i);
+ if (profile) slc->data[1] = profile;
+ if (level) slc->data[3] = level;
+ }
+ e = gf_isom_avc_config_update(file, track, 1, avcc);
+ assert (e == GF_OK);
+ gf_odf_avc_cfg_del(avcc);
+ return GF_OK;
+}
+
+#endif /*GPAC_DISABLE_MEDIA_IMPORT*/
+
+
GF_EXPORT
GF_Err gf_media_change_par(GF_ISOFile *file, u32 track, s32 ar_num, s32 ar_den)
{
}
return gf_isom_set_track_layout_info(file, track, tk_w<<16, tk_h<<16, 0, 0, 0);
}
-
-
-GF_EXPORT
-GF_Err gf_media_change_pl(GF_ISOFile *file, u32 track, u32 profile, u32 level)
-{
- u32 i, count, stype;
- GF_Err e;
- GF_AVCConfig *avcc;
-
- stype = gf_isom_get_media_subtype(file, track, 1);
- switch (stype) {
- case GF_ISOM_SUBTYPE_AVC_H264:
- case GF_ISOM_SUBTYPE_AVC2_H264:
- break;
- default:
- return GF_OK;
- }
-
- avcc = gf_isom_avc_config_get(file, track, 1);
- if (level) avcc->AVCLevelIndication = level;
- if (profile) avcc->AVCProfileIndication = profile;
- count = gf_list_count(avcc->sequenceParameterSets);
- for (i=0; i<count; i++) {
- GF_AVCConfigSlot *slc = gf_list_get(avcc->sequenceParameterSets, i);
- if (profile) slc->data[1] = profile;
- if (level) slc->data[3] = level;
- }
- e = gf_isom_avc_config_update(file, track, 1, avcc);
- assert (e == GF_OK);
- gf_odf_avc_cfg_del(avcc);
- return GF_OK;
-}
-
-#endif /*GPAC_DISABLE_MEDIA_IMPORT*/
pe->codecs[len-2] = 0;
}
-#ifndef GPAC_DISABLE_MEDIA_IMPORT
width = height = samplerate = num_channels = 0;
+#ifndef GPAC_DISABLE_MEDIA_IMPORT
if (do_import) {
GF_Err e;
GF_MediaImporter import;
}
+#ifndef GPAC_DISABLE_MEDIA_IMPORT
static void gf_text_import_set_language(GF_MediaImporter *import, u32 track)
{
if (import->esd && import->esd->langDesc) {
gf_isom_set_media_language(import->dest, track, lang);
}
}
-
+#endif
static char *gf_text_get_utf8_line(char *szLine, u32 lineSize, FILE *txt_in, s32 unicode_type)
{
return sOK;
}
+
+#ifndef GPAC_DISABLE_MEDIA_IMPORT
+
static GF_Err gf_text_import_srt(GF_MediaImporter *import)
{
FILE *srt_in;
}
}
+#endif /*GPAC_DISABLE_MEDIA_IMPORT*/
+
#endif /*GPAC_DISABLE_ISOM_WRITE*/
#include <gpac/internal/odf_dev.h>
-#ifndef GPAC_DISABLE_OD_DUMP
+#if !defined(GPAC_DISABLE_OD_DUMP) && !defined(GPAC_MINIMAL_ODF)
#define GF_IPMPX_MAX_TREE 100
DumpInt(trace, "controlPointCode", ipmp->control_point, indent, XMTDump);
if (ipmp->control_point) DumpInt(trace, "sequenceCode", ipmp->cp_sequence_code, indent, XMTDump);
EndAttributes(trace, indent, XMTDump);
+#ifndef GPAC_MINIMAL_ODF
/*parse IPMPX data*/
StartElement(trace, "IPMPX_Data", indent, XMTDump, 1);
indent++;
}
indent--;
EndElement(trace, "IPMPX_Data", indent, XMTDump, 1);
+#endif
}
else if (!ipmp->IPMPS_Type) {
DumpString(trace, "URLString", ipmp->opaque_data, indent, XMTDump);
if (t->tool_url) DumpString(trace, "ToolURL", t->tool_url, indent, XMTDump);
if (t->toolParamDesc) {
StartElement(trace, "toolParamDesc" , indent, XMTDump, 0);
+#ifndef GPAC_MINIMAL_ODF
gf_ipmpx_dump_data((GF_IPMPX_Data *)t->toolParamDesc, trace, indent + (XMTDump ? 1 : 0), XMTDump);
+#endif
EndElement(trace, "toolParamDesc" , indent, XMTDump, 0);
}
EndAttributes(trace, indent, XMTDump);
}
+#ifndef GPAC_MINIMAL_ODF
+
GF_EXPORT
GF_Err gf_oci_dump_event(OCIEvent *ev, FILE *trace, u32 indent, Bool XMTDump)
{
return e;
}
+#endif /*GPAC_MINIMAL_ODF*/
+
#endif /*GPAC_DISABLE_OD_DUMP*/
#include <gpac/media_tools.h>
-#if !defined(GPAC_DISABLE_LOADER_BT) && !defined(GPAC_DISABLE_LOADER_XMT)
-
/* to complete...*/
u32 gf_odf_get_field_type(GF_Descriptor *desc, char *fieldName)
return 0;
}
-#endif /* defined(GPAC_DISABLE_LOADER_BT) || defined(GPAC_DISABLE_LOADER_XMT)*/
static void gf_sm_finalize_mux(GF_ISOFile *mp4, GF_ESD *src, u32 offset_ts)
{
-#if !defined (GPAC_DISABLE_ISOM) || !defined(GPAC_DISABLE_ISOM_WRITE)
+#if !defined (GPAC_DISABLE_ISOM) && !defined(GPAC_DISABLE_ISOM_WRITE)
u32 track, mts, ts;
GF_MuxInfo *mux = gf_sm_get_mux_info(src);
if (!mux && !offset_ts) return;
}
if (rewrite_esd_only) return GF_OK;
+#ifndef GPAC_DISABLE_ISOM_WRITE
/*what's the media type for input sensor ??*/
len = gf_isom_new_track(mp4, src->ESID, GF_ISOM_MEDIA_SCENE, 1000);
if (!len) return gf_isom_last_error(mp4);
gf_isom_set_track_enabled(mp4, len, 1);
if (!src->ESID) src->ESID = gf_isom_get_track_id(mp4, len);
return gf_isom_new_mpeg4_description(mp4, len, src, NULL, NULL, &i);
+#else
+ return GF_NOT_SUPPORTED;
+#endif
}
+#ifndef GPAC_DISABLE_MEDIA_IMPORT
+
static GF_Err gf_sm_import_stream(GF_SceneManager *ctx, GF_ISOFile *mp4, GF_ESD *src, Double imp_time, char *mediaSource, Bool od_sample_rap)
{
u32 track, di, i;
return GF_OK;
}
+
+#endif /*GPAC_DISABLE_MEDIA_IMPORT*/
+
/*locate stream in all OD updates/ESD updates (needed for systems tracks)*/
static GF_ESD *gf_sm_locate_esd(GF_SceneManager *ctx, u16 ES_ID)
{
return NULL;
}
+
+#ifndef GPAC_DISABLE_ISOM_WRITE
+
static GF_Err gf_sm_encode_scene(GF_SceneManager *ctx, GF_ISOFile *mp4, GF_SMEncodeOptions *opts, u32 scene_type)
{
char *data;
if (!au && !esd->URLString) {
/*if not in IOD, the stream will be imported when encoding the OD stream*/
if (!is_in_iod) continue;
+#ifndef GPAC_DISABLE_MEDIA_IMPORT
e = gf_sm_import_stream(ctx, mp4, esd, 0, NULL, 0);
+#else
+ e = GF_BAD_PARAM;
+#endif
if (e) goto exit;
gf_sm_finalize_mux(mp4, esd, 0);
gf_isom_add_track_to_root_od(mp4, gf_isom_get_track_by_id(mp4, esd->ESID));
switch (imp_esd->tag) {
case GF_ODF_ESD_TAG:
+#ifndef GPAC_DISABLE_MEDIA_IMPORT
e = gf_sm_import_stream(ctx, mp4, imp_esd, au->timing_sec, mediaSource, au->flags & GF_SM_AU_RAP);
+#else
+ e = GF_BAD_PARAM;
+#endif
if (e) {
GF_LOG(GF_LOG_ERROR, GF_LOG_CONTAINER, ("[ISO File Encode] cannot import stream %d (error %s)\n", imp_esd->ESID, gf_error_to_string(e)));
goto err_exit;
while ((imp_esd = (GF_ESD*)gf_list_enum(esdU->ESDescriptors, &m))) {
switch (imp_esd->tag) {
case GF_ODF_ESD_TAG:
+#ifndef GPAC_DISABLE_MEDIA_IMPORT
e = gf_sm_import_stream(ctx, mp4, imp_esd, au->timing_sec, mediaSource, au->flags & GF_SM_AU_RAP);
+#else
+ e = GF_BAD_PARAM;
+#endif
if (e) {
GF_LOG(GF_LOG_ERROR, GF_LOG_CONTAINER, ("[ISO File Encode] cannot import stream %d (error %s)\n", imp_esd->ESID, gf_error_to_string(e)));
gf_odf_com_del(&com);
gf_isom_modify_alternate_brand(mp4, GF_ISOM_BRAND_MP41, 1);
/*import specials, that is input remapping to BIFS*/
+#ifndef GPAC_DISABLE_MEDIA_IMPORT
e = gf_sm_import_specials(ctx);
+#else
+ e = GF_BAD_PARAM;
+#endif
if (e) return e;
return GF_OK;
}
+#endif /*GPAC_DISABLE_ISOM_WRITE*/
+
#endif /*GPAC_DISABLE_SCENE_ENCODER*/
-#ifndef GPAC_DISABLE_LOADER_ISOM
+#if !defined(GPAC_DISABLE_ISOM) && !defined(GPAC_DISABLE_LOADER_ISOM)
static void UpdateODCommand(GF_ISOFile *mp4, GF_ODCom *com)
{
return GF_OK;
}
-#endif /*GPAC_DISABLE_LOADER_ISOM*/
+#endif /*GPAC_DISABLE_ISOM && GPAC_DISABLE_LOADER_ISOM*/
case GF_SG_VRML_MFNODE:
needs_field_container = 0;
if (sdump->XMLDump && sdump->X3DDump) needs_field_container = gf_dump_vrml_needs_container(node, &field);
+#ifndef GPAC_DISABLE_X3D
if (!sdump->X3DDump) {
if (gf_node_get_tag(node)==TAG_X3D_Switch) field.name = "choice";
}
+#endif
list = * ((GF_ChildNodeItem **) field.far_ptr);
assert(list);
if (!sdump->XMLDump || !sdump->X3DDump) StartList(sdump, field.name);
name = gf_node_get_class_name(node);
#ifndef GPAC_DISABLE_X3D
tag = gf_node_x3d_type_by_class_name(name);
-#endif
return tag ? 1 : 0;
+#else
+ return 0;
+#endif
} else {
if (node->sgprivate->tag<=GF_NODE_RANGE_LAST_MPEG4) return 1;
+#ifndef GPAC_DISABLE_X3D
if (node->sgprivate->tag==TAG_X3D_Rectangle2D) return 1;
if (node->sgprivate->tag==TAG_X3D_Circle2D) return 1;
+#endif
name = gf_node_get_class_name(node);
tag = gf_node_mpeg4_type_by_class_name(name);
return tag ? 1 : 0;
if (sdump->X3DDump) {
if (node->sgprivate->tag == TAG_MPEG4_Circle) name = "Circle2D";
else if (node->sgprivate->tag == TAG_MPEG4_Rectangle) name = "Rectangle2D";
+#ifndef GPAC_DISABLE_X3D
} else if (!sdump->X3DDump) {
if (node->sgprivate->tag == TAG_X3D_Circle2D) name = "Circle";
else if (node->sgprivate->tag == TAG_X3D_Rectangle2D) name = "Rectangle";
+#endif
}
#endif
base = NULL;
switch (gf_node_get_tag(node)) {
#ifndef GPAC_DISABLE_VRML
+#ifndef GPAC_DISABLE_X3D
case TAG_X3D_Script:
+#endif
case TAG_MPEG4_Script:
isScript = 1;
break;
gf_dump_vrml_field(sdump, node, field);
}
} else {
+#ifndef GPAC_DISABLE_X3D
/*X3D script metadata, NOT DYN*/
if ((i==3) && (node->sgprivate->tag==TAG_X3D_Script) ) {
if (*((GF_Node **)field.far_ptr)) gf_dump_vrml_field(sdump, node, field);
- } else {
+ } else
+#endif
+ {
gf_dump_vrml_dyn_field(sdump, node, field, 0);
}
}
static GF_Err gf_seng_encode_dims_au(GF_SceneEngine *seng, u16 ESID, GF_List *commands, char **data, u32 *size)
{
- GF_Err e;
+#ifndef GPAC_DISABLE_SCENE_DUMP
GF_SceneDumper *dumper = NULL;
+#endif
+ GF_Err e;
char rad_name[4096];
char file_name[4096];
FILE *file = NULL;
#endif
}
+#ifndef GPAC_DISABLE_SCENE_DUMP
dumper = gf_sm_dumper_new(seng->ctx->scene_graph, rad_name, ' ', GF_SM_DUMP_SVG);
if (!dumper) {
GF_LOG(GF_LOG_ERROR, GF_LOG_CONTAINER, ("[SceneEngine] Cannot create SVG dumper for %s.svg\n", rad_name));
e = GF_IO_ERR;
goto exit;
- }
+ }
if (commands && gf_list_count(commands)) {
e = gf_sm_dump_command_list(dumper, commands, 0, 0);
- } else {
+ }
+ else {
e = gf_sm_dump_graph(dumper, 0, 0);
}
gf_sm_dumper_del(dumper);
GF_LOG(GF_LOG_ERROR, GF_LOG_CONTAINER, ("[SceneEngine] Cannot dump DIMS Commands\n"));
goto exit;
}
+#endif
+
#ifdef DUMP_DIMS_LOG_WITH_TIME
if (do_dump_with_time) {
do_dump_with_time = 0;
break;
#endif
-#ifndef GPAC_DISABLE_BIFS_ENC
+#ifndef GPAC_DISABLE_LASER
case GPAC_OTI_SCENE_LASER:
e = gf_laser_encode_au(seng->lsrenc, sc->ESID, au->commands, 0, &data, &size);
break;
GF_EXPORT
GF_Err gf_seng_save_context(GF_SceneEngine *seng, char *ctxFileName)
{
+#ifdef GPAC_DISABLE_SCENE_DUMP
+ return GF_NOT_SUPPORTED;
+#else
u32 d_mode, do_enc;
char szF[GF_MAX_PATH], *ext;
GF_Err e;
e = gf_sm_dump(seng->ctx, ctxFileName ? szF : NULL, d_mode);
}
return e;
+#endif
}
static GF_AUContext *gf_seng_create_new_au(GF_StreamContext *sc, u32 time)
break;
#endif
-#ifndef GPAC_DISABLE_BIFS_ENC
+#ifndef GPAC_DISABLE_LASER
case GPAC_OTI_SCENE_LASER:
e = gf_laser_encode_au(seng->lsrenc, ESID, new_au->commands, 0, &data, &size);
break;
if (seng->bifsenc) gf_bifs_encoder_del(seng->bifsenc);
#endif
-#ifndef GPAC_DISABLE_BIFS_ENC
+#ifndef GPAC_DISABLE_LASER
if (seng->lsrenc) gf_laser_encoder_del(seng->lsrenc);
#endif
DEF_EXC(TYPE_MISMATCH_ERR);
#undef DEF_EXC
- JS_AliasProperty(c, global, "DOMException", "e");
+ //JS_AliasProperty(c, global, "DOMException", "e");
obj = JS_DefineObject(c, global, "EventException", NULL, 0, 0);
JS_DefineProperty(c, obj, "UNSPECIFIED_EVENT_TYPE_ERR", INT_TO_JSVAL(0), 0, 0, JSPROP_READONLY | JSPROP_PERMANENT);
JS_DefineProperty(c, obj, "DISPATCH_REQUEST_ERR", INT_TO_JSVAL(1), 0, 0, JSPROP_READONLY | JSPROP_PERMANENT);
GF_SceneGraph *sg = NULL;
JSFunction*fun = NULL;
GF_Node *n = NULL;
- jsval funval = 0;
+ jsval funval = JSVAL_NULL;
JSObject *evt_handler;
SMJS_OBJ
SMJS_ARGS
if (!callback) {
handler->js_fun = fun;
- handler->js_fun_val = funval;
+ handler->js_fun_val = *(u64 *) &funval;
if (handler->js_fun_val) {
handler->js_context = c;
/*protect the function - we don't know how it was passed to us, so prevent it from being GCed*/
u32 evtType, i, count;
char *inNS = NULL;
GF_Node *node = NULL;
- jsval funval = 0;
+ jsval funval = JSVAL_NULL;
GF_SceneGraph *sg = NULL;
GF_DOMEventTarget *target = NULL;
SMJS_OBJ
funval = argv[of+1];
}
}
- if (!callback && !funval) goto err_exit;
+ if (!callback && JSVAL_IS_NULL(funval) ) goto err_exit;
evtType = gf_dom_event_type_by_name(type);
if (evtType==GF_EVENT_UNKNOWN) goto err_exit;
if (!info.far_ptr) continue;
hdl = (SVG_handlerElement *) ((XMLRI*)info.far_ptr)->target;
if (!hdl) continue;
- if (funval) {
- if (funval != (jsval) hdl->js_fun_val) continue;
+ if (! JSVAL_IS_NULL(funval) ) {
+ if (*(u64 *) &funval != hdl->js_fun_val) continue;
} else if (hdl->children) {
txt = (GF_DOMText *) hdl->children->node;
if (txt->sgprivate->tag != TAG_DOMText) continue;
JSObject *dom_js_define_event(JSContext *c, JSObject *global)
{
JSObject *obj = JS_DefineObject(c, global, "evt", &dom_rt->domEventClass, 0, 0 );
- JS_AliasProperty(c, global, "evt", "event");
+ //JS_AliasProperty(c, global, "evt", "event");
return obj;
}
JSContext *ctx;
GF_Mutex *mx;
-
JSClass SFNodeClass;
#ifndef GPAC_DISABLE_VRML
}
+#ifdef NO_JS_RUNTIMETHREAD
+void JS_SetRuntimeThread(JSRuntime *jsr)
+{
+}
+void JS_ClearRuntimeThread(JSRuntime *jsr)
+{
+}
+#endif
+
+
#ifdef __SYMBIAN32__
const long MAX_HEAP_BYTES = 256 * 1024L;
#else
}
js_rt->nb_inst++;
ctx = JS_NewContext(js_rt->js_runtime, STACK_CHUNK_BYTES);
+ JS_SetOptions(ctx, JS_GetOptions(ctx) | JSOPTION_WERROR);
+
+#ifdef JS_THREADSAFE
+#if (JS_VERSION>=185)
+ JS_ClearContextThread(ctx);
+ JS_ClearRuntimeThread(js_rt->js_runtime);
+#endif
+#endif
return ctx;
}
void gf_sg_ecmascript_del(JSContext *ctx)
{
#ifdef JS_THREADSAFE
- JS_ClearContextThread(ctx);
+#if (JS_VERSION>=185)
+ assert(js_rt);
+ JS_SetRuntimeThread(js_rt->js_runtime);
JS_SetContextThread(ctx);
+#endif
#endif
JS_DestroyContext(ctx);
// gf_js_remove_root(priv->js_ctx, &r->obj);
r->obj=NULL;
}
- if (r->fun) {
+ if ( ! JSVAL_IS_VOID(r->fun)) {
// gf_js_remove_root(priv->js_ctx, &r->fun);
- r->fun=0;
+ r->fun=JSVAL_NULL;
}
return;
}
if (!JSVAL_IS_OBJECT(argv[0]) || !JS_InstanceOf(c, JSVAL_TO_OBJECT(argv[0]), &js_rt->SFNodeClass, NULL) ) return JS_FALSE;
- if (JSVAL_IS_STRING(argv[1]) && (argv[2]==JSVAL_NULL) && (argv[3]==JSVAL_NULL)) {
+ if (JSVAL_IS_STRING(argv[1]) && JSVAL_IS_NULL(argv[2]) && JSVAL_IS_NULL(argv[3])) {
ptr = (GF_JSField *) JS_GetPrivate(c, JSVAL_TO_OBJECT(argv[0]));
assert(ptr->field.fieldType==GF_SG_VRML_SFNODE);
n1 = * ((GF_Node **)ptr->field.far_ptr);
GF_Node *n;
GF_ScriptField *sf;
GF_FieldInfo info;
- JSString *str = JS_ValueToString(c, id);
+ jsval idval;
+ JSString *str;
+ JS_IdToValue(c, id, &idval);
+ if (! SMJS_ID_IS_STRING(id)) return JS_FALSE;
+ str = SMJS_ID_TO_STRING(id);
if (!str) return JS_FALSE;
script = JS_GetScriptStack(c);
if(parent) gf_node_get_field(parent, field->fieldIndex, &jsf->field); \
#define SETUP_MF_FIELD \
+ if (!obj) return JSVAL_NULL; \
jsf = (GF_JSField *) JS_GetPrivate(priv->js_ctx, obj); \
jsf->owner = parent; \
if (parent) gf_node_get_field(parent, field->fieldIndex, &jsf->field); \
#ifdef GPAC_HAS_SPIDERMONKEY
+/*
+ * locking/try-locking the JS context
+ * we need to test whether the calling thread already has the lock on the script context
+ * if this is not the case (i.e. first lock on mutex), we switch JS context threads and
+ * call begin/end requests. Nesting begin/end request in a reentrant way crashes JS
+ * (mozilla doc is wrong here)
+ *
+ * */
void gf_sg_lock_javascript(struct JSContext *cx, Bool LockIt)
{
if (!js_rt) return;
+ assert(cx);
if (LockIt) {
gf_mx_p(js_rt->mx);
#ifdef JS_THREADSAFE
- if (cx) {
+ if (gf_mx_get_num_locks(js_rt->mx)==1) {
#if (JS_VERSION>=185)
- JS_SetContextThread(cx);
+ JS_SetRuntimeThread(js_rt->js_runtime);
+ JS_SetContextThread(cx);
#endif
JS_BeginRequest(cx);
}
#endif
} else {
#ifdef JS_THREADSAFE
- if (cx) {
+ if (gf_mx_get_num_locks(js_rt->mx)==1) {
JS_EndRequest(cx);
#if (JS_VERSION>=185)
- JS_ClearContextThread(cx);
+ JS_ClearContextThread(cx);
+ JS_ClearRuntimeThread(js_rt->js_runtime);
#endif
}
#endif
Bool gf_sg_try_lock_javascript(struct JSContext *cx)
{
+ assert(cx);
if (gf_mx_try_lock(js_rt->mx)) {
#ifdef JS_THREADSAFE
- if (cx) {
+ if (gf_mx_get_num_locks(js_rt->mx)==1) {
#if (JS_VERSION>=185)
- JS_SetContextThread(cx);
+ JS_SetRuntimeThread(js_rt->js_runtime);
+ JS_SetContextThread(cx);
#endif
JS_BeginRequest(cx);
}
s32 src_row;
u32 i, yuv_planar_type = 0;
Bool no_memcpy;
+ Bool force_load_odd_yuv_lines = 0;
Bool yuv_init = 0;
Bool has_alpha = (alpha!=0xFF) ? 1 : 0;
u32 dst_bpp, dst_w_size;
tmp = (u8 *) gf_malloc(sizeof(u8) * src_w * (yuv_planar_type ? 8 : 4) );
rows = tmp;
+ if ( (src_h / dst_h) * dst_h != src_h) force_load_odd_yuv_lines = 1;
+
dst_bits = (u8 *) dst->video_buffer;
pos_y = 0x10000;
if (prev_row != src_row) {
u32 the_row = src_row - 1;
if (yuv_planar_type) {
- if ( the_row % 2) {
- if (!yuv_init) {
+ if (the_row % 2) {
+ if (!yuv_init || force_load_odd_yuv_lines) {
yuv_init = 1;
the_row --;
if (flip) the_row = src->height-2 - the_row;
if (key) {
for (i=0; i<src_w; i++) {
u32 idx = 4*i;
- s32 thres;
- thres = (255 + (tmp[idx]-kr)) % 255;
- thres += (255 + (tmp[idx+1]-kg)) % 255;
- thres += (255 + (tmp[idx+2]-kb)) % 255;
- if (thres > 3*0xFE) tmp[idx+3] = ka;
-// if ( (tmp[idx]==kr) && (tmp[idx+1]==kg) && (tmp[idx+2]==kb)) tmp[idx+3] = ka;
+ s32 thres, v;
+ v = tmp[idx]-kr; thres = ABS(v);
+ v = tmp[idx+1]-kg; thres += ABS(v);
+ v = tmp[idx+2]-kb; thres += ABS(v);
+ thres/=3;
+#if 0
+ if (thres < kl) tmp[idx+3] = 0;
+ else if (thres <= kh) tmp[idx+3] = (thres-kl)*ka / (kh-kl);
+#else
+ if (thres < kh) tmp[idx+3] = 0;
+#endif
+ else tmp[idx+3] = ka;
}
}
}