?? pbc.c
字號:
/* $Id: pbc.c,v 1.3 2005/01/01 02:43:59 rockyb Exp $ Copyright (C) 2000, 2004 Herbert Valerio Riedel <hvr@gnu.org> 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*/#ifdef HAVE_CONFIG_H# include "config.h"#endif#include <string.h>#include <stddef.h>#include <math.h>#include <cdio/cdio.h>#include <cdio/bytesex.h>/* Public headers */#include <libvcd/logging.h>#include <libvcd/files.h>#include <libvcd/types.h>#include <libvcd/info.h>/* FIXME! Make this really private. */#include <libvcd/files_private.h>/* Private headers */#include "vcd_assert.h"#include "obj.h"#include "pbc.h"#include "util.h"static const char _rcsid[] = "$Id: pbc.c,v 1.3 2005/01/01 02:43:59 rockyb Exp $";static uint8_t_wtime (int seconds){ if (seconds < 0) return 255; if (seconds <= 60) return seconds; if (seconds <= 2000) { double _tmp; _tmp = seconds; _tmp -= 60; _tmp /= 10; _tmp += 60; return rint (_tmp); } vcd_warn ("wait time of %ds clipped to 2000s", seconds); return 254;}static pbc_t *_vcd_pbc_byid(const VcdObj *obj, const char item_id[]){ CdioListNode *node; _CDIO_LIST_FOREACH (node, obj->pbc_list) { pbc_t *_pbc = _cdio_list_node_data (node); if (_pbc->id && !strcmp (item_id, _pbc->id)) return _pbc; } /* not found */ return NULL;}unsigned_vcd_pbc_lid_lookup (const VcdObj *obj, const char item_id[]){ CdioListNode *node; unsigned n = 1; _CDIO_LIST_FOREACH (node, obj->pbc_list) { pbc_t *_pbc = _cdio_list_node_data (node); vcd_assert (n < 0x8000); if (_pbc->id && !strcmp (item_id, _pbc->id)) return n; n++; } /* not found */ return 0;}static void_set_area_helper (pbc_area_t *dest, const pbc_area_t *src, const char sel_id[]){ memset (dest, 0, sizeof (pbc_area_t)); if (src) { if (src->x1 || src->x2 || src->y1 || src->y2) /* not disabled */ { if (src->x1 >= src->x2) vcd_error ("selection '%s': area x1 >= x2 (%d >= %d)", sel_id, src->x1, src->x2); if (src->y1 >= src->y2) vcd_error ("selection '%s': area y1 >= y2 (%d >= %d)", sel_id, src->y1, src->y2); } *dest = *src; }}enum item_type_t_vcd_pbc_lookup (const VcdObj *obj, const char item_id[]){ unsigned id; vcd_assert (item_id != NULL); if ((id = _vcd_pbc_pin_lookup (obj, item_id))) { if (id < 2) return ITEM_TYPE_NOTFOUND; else if (id < MIN_ENCODED_TRACK_NUM) return ITEM_TYPE_TRACK; else if (id < 600) return ITEM_TYPE_ENTRY; else if (id <= MAX_ENCODED_SEGMENT_NUM) return ITEM_TYPE_SEGMENT; else vcd_assert_not_reached (); } else if (_vcd_pbc_lid_lookup (obj, item_id)) return ITEM_TYPE_PBC; return ITEM_TYPE_NOTFOUND;}uint16_t_vcd_pbc_pin_lookup (const VcdObj *obj, const char item_id[]){ int n; CdioListNode *node; if (!item_id) return 0; /* check sequence items */ n = 0; _CDIO_LIST_FOREACH (node, obj->mpeg_sequence_list) { mpeg_sequence_t *_sequence = _cdio_list_node_data (node); vcd_assert (n < 98); if (_sequence->id && !strcmp (item_id, _sequence->id)) return n + 2; n++; } /* check entry points */ n = 0; _CDIO_LIST_FOREACH (node, obj->mpeg_sequence_list) { mpeg_sequence_t *_sequence = _cdio_list_node_data (node); CdioListNode *node2; /* default entry point */ if (_sequence->default_entry_id && !strcmp (item_id, _sequence->default_entry_id)) return n + 100; n++; /* additional entry points */ _CDIO_LIST_FOREACH (node2, _sequence->entry_list) { entry_t *_entry = _cdio_list_node_data (node2); vcd_assert (n < 500); if (_entry->id && !strcmp (item_id, _entry->id)) return n + 100; n++; } } /* check sequence items */ n = 0; _CDIO_LIST_FOREACH (node, obj->mpeg_segment_list) { mpeg_segment_t *_segment = _cdio_list_node_data (node); vcd_assert (n < 1980); if (_segment->id && !strcmp (item_id, _segment->id)) return n + MIN_ENCODED_SEGMENT_NUM; n += _segment->segment_count; } return 0;}bool_vcd_pbc_available (const VcdObj *obj){ vcd_assert (obj != NULL); vcd_assert (obj->pbc_list != NULL); if (!_cdio_list_length (obj->pbc_list)) return false; if (!_vcd_obj_has_cap_p (obj, _CAP_PBC)) { vcd_warn ("PBC list not empty but VCD type not capable of PBC!"); return false; } return true;}uint16_t_vcd_pbc_max_lid (const VcdObj *obj){ uint16_t retval = 0; if (_vcd_pbc_available (obj)) retval = _cdio_list_length (obj->pbc_list); return retval;}static size_t_vcd_pbc_node_length (const VcdObj *obj, const pbc_t *_pbc, bool extended){ size_t retval = 0; if (extended) vcd_assert (_vcd_obj_has_cap_p (obj, _CAP_PBC_X)); switch (_pbc->type) { int n; case PBC_PLAYLIST: n = _cdio_list_length (_pbc->item_id_list); retval = __cd_offsetof (_PsdPlayListDescriptor, itemid[n]); break; case PBC_SELECTION: n = _cdio_list_length (_pbc->select_id_list); retval = __cd_offsetof (PsdSelectionListDescriptor_t, ofs[n]); if (extended || _vcd_obj_has_cap_p (obj, _CAP_4C_SVCD)) retval += __cd_offsetof (PsdSelectionListDescriptorExtended, area[n]); break; case PBC_END: retval = sizeof (PsdEndListDescriptor); break; default: vcd_assert_not_reached (); break; } return retval;}static uint16_t _lookup_psd_offset (const VcdObj *obj, const char item_id[], bool extended){ CdioListNode *node; if (extended) vcd_assert (_vcd_obj_has_cap_p (obj, _CAP_PBC_X)); /* disable it */ if (!item_id) return PSD_OFS_DISABLED; _CDIO_LIST_FOREACH (node, obj->pbc_list) { pbc_t *_pbc = _cdio_list_node_data (node); if (!_pbc->id || strcmp (item_id, _pbc->id)) continue; return (extended ? _pbc->offset_ext : _pbc->offset) / INFO_OFFSET_MULT; } vcd_error ("PSD: referenced PSD '%s' not found", item_id); /* not found */ return PSD_OFS_DISABLED;}static void_vcd_pin_mark_id (const VcdObj *obj, const char _id[]){ mpeg_sequence_t *_seq; mpeg_segment_t *_seg; vcd_assert (obj != NULL); if (!_id) return; if ((_seq = _vcd_obj_get_sequence_by_id ((VcdObj *) obj, _id))) _seq->referenced = true; if ((_seg = _vcd_obj_get_segment_by_id ((VcdObj *) obj, _id))) _seg->referenced = true;}static void_vcd_pbc_mark_id (const VcdObj *obj, const char _id[]){ pbc_t *_pbc; vcd_assert (obj != NULL); if (!_id) return; _pbc = _vcd_pbc_byid (obj, _id); if (!_pbc) /* not found */ return; if (_pbc->referenced) /* already marked */ return; _pbc->referenced = true; switch (_pbc->type) { case PBC_PLAYLIST: { CdioListNode *node; _vcd_pbc_mark_id (obj, _pbc->prev_id); _vcd_pbc_mark_id (obj, _pbc->next_id); _vcd_pbc_mark_id (obj, _pbc->retn_id); _CDIO_LIST_FOREACH (node, _pbc->item_id_list) { const char *_id = _cdio_list_node_data (node); _vcd_pin_mark_id (obj, _id); } } break; case PBC_SELECTION: { CdioListNode *node; _vcd_pbc_mark_id (obj, _pbc->prev_id); _vcd_pbc_mark_id (obj, _pbc->next_id); _vcd_pbc_mark_id (obj, _pbc->retn_id); if (_pbc->selection_type == _SEL_NORMAL) _vcd_pbc_mark_id (obj, _pbc->default_id); _vcd_pbc_mark_id (obj, _pbc->timeout_id); _vcd_pin_mark_id (obj, _pbc->item_id); _CDIO_LIST_FOREACH (node, _pbc->select_id_list) { const char *_id = _cdio_list_node_data (node); _vcd_pbc_mark_id (obj, _id); } } break; case PBC_END: _vcd_pin_mark_id (obj, _pbc->image_id); break; default: vcd_assert_not_reached (); break; }}void_vcd_pbc_check_unreferenced (const VcdObj *obj){ CdioListNode *node; /* clear all flags */ _CDIO_LIST_FOREACH (node, obj->pbc_list) { pbc_t *_pbc = _cdio_list_node_data (node); _pbc->referenced = false; } _CDIO_LIST_FOREACH (node, obj->mpeg_sequence_list) { mpeg_sequence_t *_sequence = _cdio_list_node_data (node); _sequence->referenced = false; } _CDIO_LIST_FOREACH (node, obj->mpeg_segment_list)
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -