diff --git a/multimedia/vdr-plugin-xineliboutput/Makefile b/multimedia/vdr-plugin-xineliboutput/Makefile index 40432273f576..1ac930de9025 100644 --- a/multimedia/vdr-plugin-xineliboutput/Makefile +++ b/multimedia/vdr-plugin-xineliboutput/Makefile @@ -1,68 +1,71 @@ # Created by: Juergen Lock PORTNAME= vdr-plugin-xineliboutput PORTVERSION= 1.0.90s20120511 PORTREVISION= 31 CATEGORIES= multimedia MASTER_SITES= SF/xineliboutput/files/xineliboutput/vdr-xineliboutput-${PORTVERSION}/:release \ LOCAL/nox:snapshot DISTFILES= ${DISTNAME}${EXTRACT_SUFX}:snapshot MAINTAINER= ports@FreeBSD.org COMMENT= Video Disk Recorder - xineliboutput plugin/viewer LICENSE= GPLv2 LICENSE_FILE= ${WRKSRC}/COPYING -BROKEN= does not build: invalid suffix on literal; C++11 requires a space between literal and identifier - -LIB_DEPENDS= libxine.so:multimedia/libxine \ - libavutil.so:multimedia/ffmpeg \ +LIB_DEPENDS= libavutil.so:multimedia/ffmpeg \ libdbus-glib-1.so:devel/dbus-glib \ - libvdpau.so:multimedia/libvdpau + libvdpau.so:multimedia/libvdpau \ + libxine.so:multimedia/libxine -PATCH_STRIP= -p1 USES= compiler:c++11-lang gl pkgconfig tar:bzip2 xorg +USE_GL= gl glu glut USE_XORG= xrandr xrender + HAS_CONFIGURE= yes -CONFIGURE_ARGS= --cc="${CC}" --cxx="${CXX}" --add-cflags=-I${VDRDIR} -USE_GL= gl glu glut -WRKSRC= ${WRKDIR}/vdr-${PLUGIN} -XINE_PLUGINSDIR=lib/xine/plugins/2.9 +CONFIGURE_ARGS= --add-cflags=-I${VDRDIR} \ + --cc="${CC}" \ + --cxx="${CXX}" -PORTDOCS= README HISTORY -PORTEXAMPLES= xine +PATCH_STRIP= -p1 + +WRKSRC= ${WRKDIR}/vdr-${PLUGIN} +XINE_PLUGINSDIR= lib/xine/plugins/2.9 PLIST_SUB= XINE_PLUGINSDIR=${XINE_PLUGINSDIR} +PORTDOCS= HISTORY README +PORTEXAMPLES= xine -OPTIONS_DEFINE= LIBBLURAY LIBEXTRACTOR EXAMPLES DOCS +OPTIONS_DEFINE= DOCS EXAMPLES LIBBLURAY LIBEXTRACTOR NLS +OPTIONS_SUB= yes -LIBEXTRACTOR_LIB_DEPENDS= libextractor.so:textproc/libextractor -LIBEXTRACTOR_CONFIGURE_ENABLE= libextractor LIBBLURAY_LIB_DEPENDS= libbluray.so:multimedia/libbluray LIBBLURAY_CONFIGURE_ENABLE= libbluray +LIBEXTRACTOR_LIB_DEPENDS= libextractor.so:textproc/libextractor +LIBEXTRACTOR_CONFIGURE_ENABLE= libextractor .include "${.CURDIR}/../vdr/Makefile.plugins" post-patch: post-patch-plugin # clang doesn't know -MG ${TOUCH} -t 200001010000 ${WRKSRC}/nosignal_720x576.c \ ${WRKSRC}/black_720x576.c ${WRKSRC}/vdrlogo_720x576.c pre-install: @${MKDIR} ${STAGEDIR}${PREFIX}/lib/vdr post-install: post-install-pluginlocales @${MKDIR} ${STAGEDIR}${PREFIX}/etc/vdr/plugins/${PLUGIN} ${INSTALL_DATA} ${WRKSRC}/examples/allowed_hosts.conf \ ${STAGEDIR}${PREFIX}/etc/vdr/plugins/${PLUGIN}/allowed_hosts.conf.sample -post-install-EXAMPLES-on: - @${MKDIR} ${STAGEDIR}${EXAMPLESDIR}/xine - ${INSTALL_DATA} ${FILESDIR}/keymap ${STAGEDIR}${EXAMPLESDIR}/xine - post-install-DOCS-on: @${MKDIR} ${STAGEDIR}${DOCSDIR} (cd ${WRKSRC} && ${INSTALL_DATA} ${PORTDOCS} ${STAGEDIR}${DOCSDIR}) +post-install-EXAMPLES-on: + @${MKDIR} ${STAGEDIR}${EXAMPLESDIR}/xine + ${INSTALL_DATA} ${FILESDIR}/keymap ${STAGEDIR}${EXAMPLESDIR}/xine + .include diff --git a/multimedia/vdr-plugin-xineliboutput/files/patch-c++11 b/multimedia/vdr-plugin-xineliboutput/files/patch-c++11 new file mode 100644 index 000000000000..ca242e5d3553 --- /dev/null +++ b/multimedia/vdr-plugin-xineliboutput/files/patch-c++11 @@ -0,0 +1,163 @@ +diff -ruN vdr-xineliboutput.orig/device.c vdr-xineliboutput/device.c +--- vdr-xineliboutput.orig/device.c 2012-05-11 09:37:27.000000000 +0200 ++++ vdr-xineliboutput/device.c 2021-08-30 10:52:36.560762000 +0200 +@@ -967,7 +967,7 @@ + #ifdef LOG_TRICKSPEED + if(PictureType != NO_PICTURE && PES_HAS_PTS(buf)) { + int64_t pts = pes_get_pts(buf, length); +- LOGMSG(" TrickSpeed: frame %s pts %"PRId64, picture_type_str[PictureType], pts); ++ LOGMSG(" TrickSpeed: frame %s pts %" PRId64, picture_type_str[PictureType], pts); + } + #endif + +@@ -1019,11 +1019,11 @@ + if(m_TrickSpeedPts == 0) { + m_TrickSpeedMode |= trs_NoAudio; + m_TrickSpeedPts = pts; +- LOGTRICKSPEED(" Seen video pts = %"PRId64, pts); ++ LOGTRICKSPEED(" Seen video pts = %" PRId64, pts); + } else { + if(pts < m_TrickSpeedPts) { + /* -> playing fast backwards */ +- LOGTRICKSPEED(" Detected fast backward mode. last %"PRId64" now %"PRId64, ++ LOGTRICKSPEED(" Detected fast backward mode. last %" PRId64 " now %" PRId64, + m_TrickSpeedPts, pts); + //if(!(m_TrickSpeedMode & trs_PTS_recalc)) + // ForEach(m_clients, &cXinelibThread::Clear); +@@ -1051,7 +1051,7 @@ + if(m_TrickSpeedPts == 0) + m_TrickSpeedPts = pts; + +- LOGTRICKSPEED(" pts %"PRId64" -> %"PRId64" (diff %"PRId64") %"PRId64"", pts, ++ LOGTRICKSPEED(" pts %" PRId64 " -> %" PRId64 " (diff %" PRId64 ") %" PRId64 "", pts, + m_TrickSpeedPts + 40*12*90, m_TrickSpeedPts + 40*12*90 - pts, + (m_TrickSpeedPts + 40*12*90)^0x80000000); + pts = m_TrickSpeedPts = m_TrickSpeedPts + 40*12*90; /* 12 frames * 40ms -> pts units */ +diff -ruN vdr-xineliboutput.orig/tools/ts.c vdr-xineliboutput/tools/ts.c +--- vdr-xineliboutput.orig/tools/ts.c 2012-05-11 09:37:27.000000000 +0200 ++++ vdr-xineliboutput/tools/ts.c 2021-08-30 10:54:49.676758000 +0200 +@@ -545,7 +545,7 @@ + + #ifdef LOG_PCR + uint epcr = ((pkt[10] & 0x1) << 8) | pkt[11]; +- LOGPCR("ts_get_pcr: PCR: %"PRId64", EPCR: %u", pcr, epcr); ++ LOGPCR("ts_get_pcr: PCR: %" PRId64 ", EPCR: %u", pcr, epcr); + #endif + + *ppcr = pcr; +diff -ruN vdr-xineliboutput.orig/xine/BluRay/decode_spuhdmv.c vdr-xineliboutput/xine/BluRay/decode_spuhdmv.c +--- vdr-xineliboutput.orig/xine/BluRay/decode_spuhdmv.c 2012-05-11 09:37:27.000000000 +0200 ++++ vdr-xineliboutput/xine/BluRay/decode_spuhdmv.c 2021-08-30 10:50:45.900369000 +0200 +@@ -925,7 +925,7 @@ + + static void decode_segment(spuhdmv_decoder_t *this) + { +- XINE_HDMV_TRACE("*** new segment, pts %010"PRId64": 0x%02x (%8d bytes)\n", ++ XINE_HDMV_TRACE("*** new segment, pts %010" PRId64 ": 0x%02x (%8d bytes)\n", + this->pts, this->buf->segment_type, this->buf->segment_len); + + switch (segbuf_segment_type(this->buf)) { +diff -ruN vdr-xineliboutput.orig/xine/BluRay/input_bluray.c vdr-xineliboutput/xine/BluRay/input_bluray.c +--- vdr-xineliboutput.orig/xine/BluRay/input_bluray.c 2012-05-11 09:37:27.000000000 +0200 ++++ vdr-xineliboutput/xine/BluRay/input_bluray.c 2021-08-30 10:54:23.289681000 +0200 +@@ -568,7 +568,7 @@ + + #ifdef LOG + int ms = this->title_info->duration / INT64_C(90); +- lprintf("Opened title %d. Length %"PRId64" bytes / %02d:%02d:%02d.%03d\n", ++ lprintf("Opened title %d. Length %" PRId64 " bytes / %02d:%02d:%02d.%03d\n", + this->current_title_idx, bd_get_title_size(this->bdh), + ms / 3600000, (ms % 3600000 / 60000), (ms % 60000) / 1000, ms % 1000); + #endif +diff -ruN vdr-xineliboutput.orig/xine/adjustable_scr.c vdr-xineliboutput/xine/adjustable_scr.c +--- vdr-xineliboutput.orig/xine/adjustable_scr.c 2012-05-11 09:37:27.000000000 +0200 ++++ vdr-xineliboutput/xine/adjustable_scr.c 2021-08-30 10:50:17.820989000 +0200 +@@ -274,13 +274,13 @@ + set_pivot( this ); + this->buffering = 1; + this->buffering_start_time = time_ms(); +- LOGMSG("start buffering at %"PRId64, this->cur_pts); ++ LOGMSG("start buffering at %" PRId64, this->cur_pts); + } + } else { + if (this->buffering) { + set_pivot( this ); + this->buffering = 0; +- LOGMSG("stop buffering at %"PRId64" (buffering took %"PRIu64" ms)", ++ LOGMSG("stop buffering at %" PRId64 " (buffering took %" PRIu64 " ms)", + this->cur_pts, elapsed(this->buffering_start_time)); + } + } +diff -ruN vdr-xineliboutput.orig/xine/demux_xvdr.c vdr-xineliboutput/xine/demux_xvdr.c +--- vdr-xineliboutput.orig/xine/demux_xvdr.c 2012-05-11 09:37:27.000000000 +0200 ++++ vdr-xineliboutput/xine/demux_xvdr.c 2021-08-30 10:51:33.112992000 +0200 +@@ -227,7 +227,7 @@ + int still_mode = (int)this->stream->metronom->get_option(this->stream->metronom, XVDR_METRONOM_STILL_MODE); + int trick_speed = (int)this->stream->metronom->get_option(this->stream->metronom, XVDR_METRONOM_TRICK_SPEED); + if (still_mode > 0 || trick_speed > 0) { +- LOGMSG("Skipping new pts %"PRId64" (still=%d trickspeed=%d)", buf->pts, still_mode, trick_speed); ++ LOGMSG("Skipping new pts %" PRId64 " (still=%d trickspeed=%d)", buf->pts, still_mode, trick_speed); + return; + } + } +@@ -239,7 +239,7 @@ + + if (this->send_newpts || (this->last_pts[video] && abs(diff)>WRAP_THRESHOLD)) { + +- LOGVERBOSE("New PTS: %"PRId64" (%s)", buf->pts, video ? "VIDEO" : "AUDIO"); ++ LOGVERBOSE("New PTS: %" PRId64 " (%s)", buf->pts, video ? "VIDEO" : "AUDIO"); + + if (this->buf_flag_seek) { + _x_demux_control_newpts(this->stream, buf->pts, BUF_FLAG_SEEK); +diff -ruN vdr-xineliboutput.orig/xine/vo_lastpts.c vdr-xineliboutput/xine/vo_lastpts.c +--- vdr-xineliboutput.orig/xine/vo_lastpts.c 2012-05-11 09:37:27.000000000 +0200 ++++ vdr-xineliboutput/xine/vo_lastpts.c 2021-08-30 10:55:43.802524000 +0200 +@@ -83,7 +83,7 @@ + if (this->xvdr_metronom) { + ASSERT_RET(this->xvdr_metronom->set_option, return); + +- LOGVERBOSE("last pts %"PRId64, vo_img->pts); ++ LOGVERBOSE("last pts %" PRId64, vo_img->pts); + + this->xvdr_metronom->set_option(this->xvdr_metronom, XVDR_METRONOM_LAST_VO_PTS, vo_img->pts); + } +diff -ruN vdr-xineliboutput.orig/xine/xvdr_metronom.c vdr-xineliboutput/xine/xvdr_metronom.c +--- vdr-xineliboutput.orig/xine/xvdr_metronom.c 2012-05-11 09:37:27.000000000 +0200 ++++ vdr-xineliboutput/xine/xvdr_metronom.c 2021-08-30 10:57:30.121628000 +0200 +@@ -37,11 +37,11 @@ + int64_t dv = this->vid_pts - this->disc_pts; + int64_t d_min = min64(da, dv); + LOGMSG(" stream A-V diff %d ms", (int)(this->vid_pts - this->aud_pts)/90); +- LOGMSG(" reported stream start at pts %"PRId64, this->disc_pts); +- LOGMSG(" output fifo end at: audio %"PRId64" video %"PRId64, this->aud_pts, this->vid_pts); +- LOGMSG(" dA %"PRId64" dV %"PRId64, da, dv); ++ LOGMSG(" reported stream start at pts %" PRId64, this->disc_pts); ++ LOGMSG(" output fifo end at: audio %" PRId64 " video %" PRId64, this->aud_pts, this->vid_pts); ++ LOGMSG(" dA %" PRId64 " dV %" PRId64, da, dv); + if (d_min < 0 && d_min > -10*90000) { +- LOGMSG(" *** output is late %"PRId64" ticks (%"PRId64" ms) ***", d_min, -d_min/90); ++ LOGMSG(" *** output is late %" PRId64 " ticks (%" PRId64 " ms) ***", d_min, -d_min/90); + this->scr->jump(this->scr, d_min); + } + this->buffering = 0; +diff -ruN vdr-xineliboutput.orig/xine_input_vdr.c vdr-xineliboutput/xine_input_vdr.c +--- vdr-xineliboutput.orig/xine_input_vdr.c 2012-05-11 09:37:27.000000000 +0200 ++++ vdr-xineliboutput/xine_input_vdr.c 2021-08-30 10:56:35.415173000 +0200 +@@ -3963,7 +3963,7 @@ + } + + if (this->discard_index != this->curpos) { +- LOGMSG("wait_stream_sync: discard_index %"PRIu64" != curpos %"PRIu64" ! (diff %"PRId64")", ++ LOGMSG("wait_stream_sync: discard_index %"PRIu64" != curpos %"PRIu64" ! (diff %" PRId64 ")", + this->discard_index, this->curpos, (int64_t)(this->discard_index - this->curpos)); + } + +@@ -3983,7 +3983,7 @@ + errno = EINTR; + } + else if (counter <= 0) { +- LOGMSG("wait_stream_sync: Timed out ! diff %"PRId64, ++ LOGMSG("wait_stream_sync: Timed out ! diff %" PRId64, + (int64_t)(this->discard_index - this->discard_index_ds)); + errno = EAGAIN; + } diff --git a/multimedia/vdr-plugin-xineliboutput/files/patch-configure b/multimedia/vdr-plugin-xineliboutput/files/patch-configure index a3be2592e1d6..5051156c313e 100644 --- a/multimedia/vdr-plugin-xineliboutput/files/patch-configure +++ b/multimedia/vdr-plugin-xineliboutput/files/patch-configure @@ -1,75 +1,93 @@ ---- a/configure -+++ a/configure -@@ -349,11 +349,14 @@ test_pkgconfig +diff -ruN b/configure a/configure +--- b/configure 2012-05-11 09:37:27.000000000 +0200 ++++ a/configure 2021-08-31 08:43:00.871579000 +0200 +@@ -234,6 +234,7 @@ + xrender + xshape + opengl ++ glx + pthread + dlfcn + vdpau +@@ -333,6 +334,7 @@ + disabled x11 && disable dbus-glib-1 xshm xrender xshape opengl xdpms xinerama vdpau + disabled vdr && disable libextractor libcap libbluray + disabled dlfcn && disable opengl ++ disabled glx && disable opengl + disabled pthread && disable opengl + disabled xrender && disable xshape xshm + } +@@ -349,11 +351,14 @@ [ $debug = yes ] && \ test_library X11 do_error "none.h" "-lnolib" -test_library VDR libextractor "extractor.h" "-lextractor" "EXTRACTOR_getKeywords(0,0)" -test_library VDR libcap "sys/capability.h" "-lcap" "cap_get_proc()" -test_library VDR libbluray "libbluray/bluray.h" "-lbluray" "bd_get_disc_info(0)" -test_library XINE libxine "xine.h" "-lxine" "xine_init(0)" -test_library DLFCN dlfcn "dlfcn.h" "-ldl" "dlopen(0,0)" +#test_library VDR libextractor "extractor.h" "-lextractor" "EXTRACTOR_getKeywords(0,0)" +test_library VDR libextractor "extractor.h" "-lextractor" "EXTRACTOR_getKeywords(0,0)" "-I${LOCALBASE}/include -L${LOCALBASE}/lib" +#test_library VDR libcap "sys/capability.h" "-lcap" "cap_get_proc()" +#test_library VDR libbluray "libbluray/bluray.h" "-lbluray" "bd_get_disc_info(0)" +test_library VDR libbluray "libbluray/bluray.h" "-lbluray" "bd_get_disc_info(0)" "-I${LOCALBASE}/include -L${LOCALBASE}/lib" +#test_library XINE libxine "xine.h" "-lxine" "xine_init(0)" +test_library XINE libxine "xine.h" "-lxine" "xine_init(0)" "-I${LOCALBASE}/include -L${LOCALBASE}/lib" +test_library DLFCN dlfcn "dlfcn.h" "" "dlopen(0,0)" if enabled libxine; then -@@ -365,24 +368,40 @@ if enabled libxine; then +@@ -365,24 +370,41 @@ fi log " $XINEPLUGINDIR" - test_library AVUTIL libavutil "libavutil/mem.h" "-lavutil" "av_mallocz(1)" - test_library JPEG libjpeg "jpeglib.h" "-ljpeg" "jpeg_create_compress(0)" - test_library X11 x11 "X11/X.h" "-lX11" "XInitThreads()" +# test_library AVUTIL libavutil "libavutil/mem.h" "-lavutil" "av_mallocz(1)" + test_library AVUTIL libavutil "libavutil/mem.h" "-lavutil" "av_mallocz(1)" "-I${LOCALBASE}/include -L${LOCALBASE}/lib" +# test_library JPEG libjpeg "jpeglib.h" "-ljpeg" "jpeg_create_compress(0)" + test_library JPEG libjpeg "jpeglib.h" "-ljpeg" "jpeg_create_compress(0)" "-I${LOCALBASE}/include -L${LOCALBASE}/lib" +# test_library X11 x11 "X11/X.h" "-lX11" "XInitThreads()" + test_library X11 x11 "X11/X.h" "-lX11" "XInitThreads()" "-I${LOCALBASE}/include -L${LOCALBASE}/lib" test_library PTHREAD pthread "pthread.h" "-lpthread" "pthread_create(0,0,0,0)" if enabled x11; then - test_library X11 xext "X11/extensions/Xext.h" "-lXext" "" - test_library X11 xshm "X11/extensions/XShm.h" "-lXext" "XShmQueryExtension(0)" - test_library X11 xrender "X11/extensions/Xrender.h" "-lXrender" "XRenderQueryFormats(0)" - test_library X11 xshape "X11/extensions/shape.h" "-lXext" "XShapeQueryExtension(0,0,0)" - test_library X11 xdpms "X11/extensions/dpms.h" "-lXext" "DPMSDisable(0)" - test_library X11 xinerama "X11/extensions/Xinerama.h" "-lXinerama" "XineramaQueryScreens(0,0)" - test_library X11 opengl "GL/glx.h" "-lGL -lGLU" "glXQueryVersion(0,0,0)" - test_library none vdpau "vdpau/vdpau_x11.h" "-lvdpau" "vdp_device_create_x11(0,0,0,0)" +# test_library X11 xext "X11/extensions/Xext.h" "-lXext" "" + test_library X11 xext "X11/extensions/Xext.h" "-lXext" "" "-I${LOCALBASE}/include -L${LOCALBASE}/lib" +# test_library X11 xshm "X11/extensions/XShm.h" "-lXext" "XShmQueryExtension(0)" + test_library X11 xshm "X11/extensions/XShm.h" "-lXext" "XShmQueryExtension(0)" "-I${LOCALBASE}/include -L${LOCALBASE}/lib" +# test_library X11 xrender "X11/extensions/Xrender.h" "-lXrender" "XRenderQueryFormats(0)" + test_library X11 xrender "X11/extensions/Xrender.h" "-lXrender" "XRenderQueryFormats(0)" "-I${LOCALBASE}/include -L${LOCALBASE}/lib" +# test_library X11 xshape "X11/extensions/shape.h" "-lXext" "XShapeQueryExtension(0,0,0)" + test_library X11 xshape "X11/extensions/shape.h" "-lXext" "XShapeQueryExtension(0,0,0)" "-I${LOCALBASE}/include -L${LOCALBASE}/lib" +# test_library X11 xdpms "X11/extensions/dpms.h" "-lXext" "DPMSDisable(0)" + test_library X11 xdpms "X11/extensions/dpms.h" "-lXext" "DPMSDisable(0)" "-I${LOCALBASE}/include -L${LOCALBASE}/lib" +# test_library X11 xinerama "X11/extensions/Xinerama.h" "-lXinerama" "XineramaQueryScreens(0,0)" + test_library X11 xinerama "X11/extensions/Xinerama.h" "-lXinerama" "XineramaQueryScreens(0,0)" "-I${LOCALBASE}/include -L${LOCALBASE}/lib" +# test_library X11 opengl "GL/glx.h" "-lGL -lGLU" "glXQueryVersion(0,0,0)" -+ test_library X11 opengl "GL/glx.h" "-lGL -lGLU" "glXQueryVersion(0,0,0)" "-I${LOCALBASE}/include -L${LOCALBASE}/lib" ++ test_library X11 opengl "GL/gl.h" "-lGL -LGLU" "glTexCoord2f(0.0,0.0)" "-I${LOCALBASE}/include -L${LOCALBASE}/lib" ++ test_library X11 glx "GL/glx.h" "-lGLX" "glXQueryVersion(0,0,0)" "-I${LOCALBASE}/include -L${LOCALBASE}/lib" +# test_library none vdpau "vdpau/vdpau_x11.h" "-lvdpau" "vdp_device_create_x11(0,0,0,0)" + test_library none vdpau "vdpau/vdpau_x11.h" "-lvdpau" "vdp_device_create_x11(0,0,0,0)" "-I${LOCALBASE}/include -L${LOCALBASE}/lib" +# test_library X11 dbus-glib-1 \ +# "dbus/dbus-glib.h" \ +# "-ldbus-glib-1 -lgobject-2.0 -lglib-2.0" \ +# "dbus_g_bus_get(0,0)" \ +# "-I/usr/include/dbus-1.0 -I/usr/lib64/dbus-1.0/include -I/usr/include/glib-2.0 -I/usr/lib64/glib-2.0/include" test_library X11 dbus-glib-1 \ "dbus/dbus-glib.h" \ "-ldbus-glib-1 -lgobject-2.0 -lglib-2.0" \ "dbus_g_bus_get(0,0)" \ - "-I/usr/include/dbus-1.0 -I/usr/lib64/dbus-1.0/include -I/usr/include/glib-2.0 -I/usr/lib64/glib-2.0/include" + "-I/usr/include/dbus-1.0 -I${LOCALBASE}/include/dbus-1.0 -I/usr/include/glib-2.0 -I${LOCALBASE}/include/glib-2.0 -L${LOCALBASE}/lib" fi fi