📄 xineplug_inp_vcd.c
字号:
/* $Id: xineplug_inp_vcd.c,v 1.53 2007/02/08 02:40:23 dsalt Exp $ Copyright (C) 2002, 2003, 2004, 2005 Rocky Bernstein <rocky@panix.com> This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA*//* These are plugin routines called by the xine engine. See Chapter 4. Extending xine's input http://xinehq.de/index.php/hackersguide/index.php?resource=5.3&action=default#INPUT and the comments in input_plugin.h This is what is referred to below a "the xine plugin spec" Please don't add any OS-specific code in here - #if defined(__sun) or or #if defined(__linux__) are harbingers of such stuff. It took a great deal of effort to get it *out* of here (or most of it); If you feel the need to do so, you are doing something wrong and breaking modularity.*/#ifdef HAVE_CONFIG_H#include "config.h"#endif/* Standard includes */#include <stdio.h>#include <stdlib.h>#include <unistd.h>#include <string.h>#include <errno.h>#include <ctype.h>#define SHORT_PLUGIN_NAME "VCD"#define MRL_PREFIX "vcd://"#define MRL_PREFIX_LEN (sizeof(MRL_PREFIX) - 1)#define MAX_DEVICE_LEN 1024#define xine_config_entry_t xine_cfg_entry_t/* Xine includes */#include "xineutils.h"#include "input_plugin.h"#include "xine-extra.h"#ifdef HAVE_VCDNAV#include <cdio/logging.h>#include <cdio/iso9660.h>#include <cdio/cd_types.h>#include <cdio/version.h>/* libvcd includes */#include <libvcd/files.h>#include <libvcd/logging.h>#else#include "cdio/logging.h"#include "cdio/iso9660.h"#include "cdio/cd_types.h"/* libvcd includes */#include "libvcd/files.h"#include "libvcd/logging.h"#endif#include "vcdplayer.h"#include "vcdio.h"/* A xine define. */#ifndef BUF_DEMUX_BLOCK#define BUF_DEMUX_BLOCK 0x05000000#endif/* Convert an autoplay enumeration into an vcdinfo itemtype enumeration. See definitions in vcdplayer.h and vcdinfo.h to get the below correct.*/static const vcdinfo_item_enum_t autoplay2itemtype[]={ VCDINFO_ITEM_TYPE_TRACK, /* VCDPLAYER_AUTOPLAY_TRACK */ VCDINFO_ITEM_TYPE_ENTRY, /* VCDPLAYER_AUTOPLAY_ENTRY */ VCDINFO_ITEM_TYPE_SEGMENT, /* VCDPLAYER_AUTOPLAY_SEGMENT */ VCDINFO_ITEM_TYPE_LID /* VCDPLAYER_AUTOPLAY_PBC */};typedef struct vcd_config_s { char *title_format; /* Format string of GUI display title */ char *comment_format; /* Format string of stream comment meta */} vcd_config_t;typedef struct vcd_input_plugin_tag vcd_input_plugin_t;typedef struct vcd_input_class_s { input_class_t input_class; xine_t *xine; config_values_t *config; /* Pointer to XineRC config file. */ vcd_input_plugin_t *ip; vcd_config_t v_config; /* config stuff passed to child */ xine_mrl_t **mrls; /* list of mrl entries for medium */ int num_mrls; /* count of above */ char *vcd_device;/* Device name to use when none specified in MRL */ /*-------------------------------------------------------------- Media resource locator (MRL) info. For the below offsets, use play_item + mrl_xxx_offset to get index into "mrls" array ---------------------------------------------------------------*/ int mrl_track_offset; /* perhaps -1 for tracks staring with 1*/ int mrl_entry_offset; /* i_tracks for entries starting with 0 */ int mrl_play_offset; /* i_tracks for entries starting with 0 */ int mrl_segment_offset; /* i_tracks + i_entries if segs start 1*/} vcd_input_class_t;vcd_input_class_t *vcd_class;struct vcd_input_plugin_tag { input_plugin_t input_plugin; /* input plugin interface as defined by by player. For xine it contains a structure of functions that need to be implemented. */ xine_stream_t *stream; xine_event_queue_t *event_queue; time_t pause_end_time; int i_old_still; /* Value of player-i_still before next read. See also i_still in vcdplayer structure. */ int i_old_deinterlace; /* value of deinterlace before entering a still. */ vcd_input_class_t *class; vcd_config_t v_config; /* Config stuff initially inherited */ char *mrl; int32_t i_mouse_button; /* The "button" number associated with the region that the mouse is currently located in. If the mouse is not in any "button" region then this has value -1. */ bool b_mouse_in; /* True if mouse is inside a "button" region; false otherwise */ vcdplayer_t player ; char *player_device;};vcd_input_plugin_t my_vcd;/* Prototype definitions */static bool vcd_handle_events (void);static void vcd_close(vcd_input_class_t *class);#if LIBVCD_VERSION_NUM >= 23static void send_mouse_enter_leave_event(vcd_input_plugin_t *p_this, bool b_mouse_in);#endif/* If class->vcd_device is NULL or the empty string, Use libcdio to find a CD drive with a VCD in it. */static boolvcd_get_default_device(vcd_input_class_t *class, bool log_msg_if_fail){ dbg_print(INPUT_DBG_CALL, "Called with %s\n", log_msg_if_fail ? "True" : "False"); if (NULL == class->vcd_device || strlen(class->vcd_device)==0) { char **cd_drives=NULL; cd_drives = cdio_get_devices_with_cap(NULL, (CDIO_FS_ANAL_SVCD|CDIO_FS_ANAL_CVD|CDIO_FS_ANAL_VIDEOCD|CDIO_FS_UNKNOWN), true); if (NULL == cd_drives || NULL == cd_drives[0]) { LOG_MSG("%s", _("failed to find a device with a VCD")); return false; } class->vcd_device = strdup(cd_drives[0]); cdio_free_device_list(cd_drives);#if LIBCDIO_VERSION_NUM <= 72 free(cd_drives);#endif } return true;}static void meta_info_assign(int field, xine_stream_t *stream, const char * info) { if (NULL != info) { dbg_print(INPUT_DBG_META, "meta[%d]: %s\n", field, info); _x_meta_info_set(stream, field, info); }}#define stream_info_assign(field, stream, info) \ _x_stream_info_set(stream, field, info);/* Set stream information. */static voidvcd_set_meta_info (vcd_input_plugin_t *xine_vcd) { vcdinfo_obj_t *p_vcdinfo= xine_vcd->player.vcd; meta_info_assign(XINE_META_INFO_ALBUM, xine_vcd->stream, vcdinfo_get_album_id(p_vcdinfo)); meta_info_assign(XINE_META_INFO_ARTIST, xine_vcd->stream, vcdinfo_get_preparer_id(p_vcdinfo)); meta_info_assign(XINE_META_INFO_COMMENT, xine_vcd->stream, vcdplayer_format_str(&xine_vcd->player, xine_vcd->v_config.comment_format)); meta_info_assign(XINE_META_INFO_GENRE, xine_vcd->stream, vcdinfo_get_format_version_str(p_vcdinfo));}static voidvcd_force_redisplay (void) {#if 1 my_vcd.stream->xine->clock->adjust_clock(my_vcd.stream->xine->clock, my_vcd.stream->xine->clock->get_current_time(my_vcd.stream->xine->clock) + 30 * 90000 );#else /* Alternate method that causes too much disruption... */ xine_set_param(my_vcd.stream, XINE_PARAM_VO_ASPECT_RATIO, (xine_get_param(my_vcd.stream, XINE_PARAM_VO_ASPECT_RATIO)));#endif}static voidvcd_set_aspect_ratio (int i_aspect_ratio) { /* Alternate method that causes too much disruption... */ xine_set_param(my_vcd.stream, XINE_PARAM_VO_ASPECT_RATIO, i_aspect_ratio);}/*! Add another MRL to the MRL list inside "this" to be displayed. mrl is the string name to add; size is the size of the entry in bytes. The number of mrls in "this" is incremented. */static voidvcd_add_mrl_slot(vcd_input_class_t *this, const char *mrl, off_t size, unsigned int *i){ dbg_print(INPUT_DBG_MRL, "called to add slot %d: %s, size %u\n", *i, mrl, (unsigned int) size); this->mrls[*i] = malloc(sizeof(xine_mrl_t)); if (NULL==this->mrls[*i]) { LOG_ERR("Can't malloc %zu bytes for MRL slot %u (%s)", sizeof(xine_mrl_t), *i, mrl); return; } this->mrls[*i]->link = NULL; this->mrls[*i]->origin = NULL; this->mrls[*i]->type = mrl_vcd; this->mrls[*i]->size = size * M2F2_SECTOR_SIZE; this->mrls[*i]->mrl = (char *) malloc(strlen(mrl) + 1); if (NULL==this->mrls[*i]->mrl) { LOG_ERR("Can't malloc %zu bytes for MRL name %s", sizeof(xine_mrl_t), mrl); } else { sprintf(this->mrls[*i]->mrl, "%s", mrl); } (*i)++;}/*! Return the associated mrl_offset for the given type.*/static int vcd_get_mrl_type_offset(vcd_input_plugin_t *inp, vcdinfo_item_enum_t type, int *size) { switch (type) { case VCDINFO_ITEM_TYPE_ENTRY: *size = inp->class->mrl_play_offset - inp->class->mrl_entry_offset + 1; return inp->class->mrl_entry_offset; break; case VCDINFO_ITEM_TYPE_SEGMENT: *size = inp->class->num_mrls - inp->class->mrl_segment_offset - 1; return inp->class->mrl_segment_offset; case VCDINFO_ITEM_TYPE_TRACK: *size = inp->class->mrl_entry_offset; return inp->class->mrl_track_offset; case VCDINFO_ITEM_TYPE_LID: /* Play list number (LID) */ *size = (inp->player.i_lids > 0) ? 1 : 0; return inp->class->mrl_play_offset; case VCDINFO_ITEM_TYPE_NOTFOUND: case VCDINFO_ITEM_TYPE_SPAREID2: default: return -2; }}/*! Create a MRL list inside "class". Any existing MRL list is freed. */static boolvcd_build_mrl_list(vcd_input_class_t *class, char *vcd_device){ char mrl[MRL_PREFIX_LEN+MAX_DEVICE_LEN+(sizeof("@E")-1)+12]; vcdplayer_t *vcdplayer; unsigned int n, i=0; unsigned int i_entries; vcdinfo_obj_t *p_vcdinfo; int was_open; if (NULL == class) { LOG_MSG("%s", _("was passed a null class parameter")); return false; } vcdplayer = &(my_vcd.player); /* If VCD already open, we gotta close and stop it. */ if ((was_open = vcdplayer->b_opened)) { vcd_close(class); } if (NULL == vcd_device) { if (!vcd_get_default_device(class, true)) return false; vcd_device = class->vcd_device; } if (!vcdio_open(vcdplayer, vcd_device)) { /* Error should have been logged in vcdio_open. If not do the below: LOG_ERR(vcdplayer, "%s: %s.\n", _("unable to open"), class->vcd_device, strerror(errno)); */ return false; } free (my_vcd.player_device); my_vcd.player_device = strdup (vcd_device); p_vcdinfo = vcdplayer->vcd; i_entries = vcdplayer->i_entries; class->mrl_track_offset = -1; xine_free_mrls(&(class->num_mrls), class->mrls); /* Figure out number of MRLs. Calculation would be real simple if didn't have to possibly remove rejected LIDs from list done in the loop below. */ class->num_mrls = vcdplayer->i_tracks + vcdplayer->i_entries + vcdplayer->i_segments + vcdplayer->i_lids; if (!vcdplayer->show_rejected && vcdinfo_get_lot(vcdplayer->vcd)) { /* Remove rejected LIDs from count. */ for (n=0; n<vcdplayer->i_lids; n++) { if ( vcdinf_get_lot_offset(vcdinfo_get_lot(vcdplayer->vcd), n) == PSD_OFS_DISABLED ) class->num_mrls--; } } class->mrls = calloc(class->num_mrls, sizeof(xine_mrl_t *)); if (NULL == class->mrls) { LOG_ERR("Can't calloc %d MRL entries", class->num_mrls); class->num_mrls = 0; if (!was_open) vcdio_close(vcdplayer); return false; } /* Record MRL's for tracks */ for (n=1; n<=vcdplayer->i_tracks; n++) { memset(&mrl, 0, sizeof (mrl)); snprintf(mrl, sizeof(mrl), "%s%s@T%u", MRL_PREFIX, vcd_device, n); vcd_add_mrl_slot(class, mrl, vcdplayer->track[n-1].size, &i); } class->mrl_entry_offset = vcdplayer->i_tracks; class->mrl_play_offset = class->mrl_entry_offset + i_entries - 1; /* Record MRL's for entries */ if (i_entries > 0) { for (n=0; n<i_entries; n++) { memset(&mrl, 0, sizeof (mrl)); snprintf(mrl, sizeof(mrl), "%s%s@E%u", MRL_PREFIX, vcd_device, n); vcd_add_mrl_slot(class, mrl, vcdplayer->entry[n].size, &i); } } /* Record MRL's for LID entries or selection entries*/ class->mrl_segment_offset = class->mrl_play_offset;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -