📄 vm.c
字号:
process_command(vm, play_Cell_post(vm));}/* Jumping */int vm_jump_pg(vm_t *vm, int pg) { (vm->state).pgN = pg; process_command(vm, play_PG(vm)); return 1;}int vm_jump_cell_block(vm_t *vm, int cell, int block) { (vm->state).cellN = cell; process_command(vm, play_Cell(vm)); /* play_Cell can jump to a different cell in case of angles */ if ((vm->state).cellN == cell) (vm->state).blockN = block; return 1;}int vm_jump_title_part(vm_t *vm, int title, int part) { link_t link; if(!set_PTT(vm, title, part)) return 0; /* Some DVDs do not want us to jump directly into a title and have * PGC pre commands taking us back to some menu. Since we do not like that, * we do not execute PGC pre commands that would do a jump. */ /* process_command(vm, play_PGC_PG(vm, (vm->state).pgN)); */ link = play_PGC_PG(vm, (vm->state).pgN); if (link.command != PlayThis) /* jump occured -> ignore it and play the PG anyway */ process_command(vm, play_PG(vm)); else process_command(vm, link); return 1;}int vm_jump_top_pg(vm_t *vm) { process_command(vm, play_PG(vm)); return 1;}int vm_jump_next_pg(vm_t *vm) { if((vm->state).pgN >= (vm->state).pgc->nr_of_programs) { /* last program -> move to TailPGC */ process_command(vm, play_PGC_post(vm)); return 1; } else { vm_jump_pg(vm, (vm->state).pgN + 1); return 1; }}int vm_jump_prev_pg(vm_t *vm) { if ((vm->state).pgN <= 1) { /* first program -> move to last program of previous PGC */ if ((vm->state).pgc->prev_pgc_nr && set_PGCN(vm, (vm->state).pgc->prev_pgc_nr)) { process_command(vm, play_PGC(vm)); vm_jump_pg(vm, (vm->state).pgc->nr_of_programs); return 1; } return 0; } else { vm_jump_pg(vm, (vm->state).pgN - 1); return 1; }}int vm_jump_up(vm_t *vm) { if((vm->state).pgc->goup_pgc_nr && set_PGCN(vm, (vm->state).pgc->goup_pgc_nr)) { process_command(vm, play_PGC(vm)); return 1; } return 0;}int vm_jump_menu(vm_t *vm, DVDMenuID_t menuid) { domain_t old_domain = (vm->state).domain; switch ((vm->state).domain) { case VTS_DOMAIN: set_RSMinfo(vm, 0, (vm->state).blockN); /* FALL THROUGH */ case VTSM_DOMAIN: case VMGM_DOMAIN: switch(menuid) { case DVD_MENU_Title: case DVD_MENU_Escape: (vm->state).domain = VMGM_DOMAIN; break; case DVD_MENU_Root: case DVD_MENU_Subpicture: case DVD_MENU_Audio: case DVD_MENU_Angle: case DVD_MENU_Part: (vm->state).domain = VTSM_DOMAIN; break; } if(get_PGCIT(vm) && set_MENU(vm, menuid)) { process_command(vm, play_PGC(vm)); return 1; /* Jump */ } else { (vm->state).domain = old_domain; } break; case FP_DOMAIN: /* FIXME XXX $$$ What should we do here? */ break; } return 0;}int vm_jump_resume(vm_t *vm) { link_t link_values = { LinkRSM, 0, 0, 0 }; if (!(vm->state).rsm_vtsN) /* Do we have resume info? */ return 0; if (!process_command(vm, link_values)) return 0; return 1;}int vm_exec_cmd(vm_t *vm, vm_cmd_t *cmd) { link_t link_values; if(vmEval_CMD(cmd, 1, &(vm->state).registers, &link_values)) return process_command(vm, link_values); else return 0; /* It updated some state thats all... */}/* getting information */int vm_get_current_menu(vm_t *vm, int *menuid) { pgcit_t* pgcit; int pgcn; pgcn = (vm->state).pgcN; pgcit = get_PGCIT(vm); *menuid = pgcit->pgci_srp[pgcn - 1].entry_id & 0xf ; return 1;}int vm_get_current_title_part(vm_t *vm, int *title_result, int *part_result) { vts_ptt_srpt_t *vts_ptt_srpt; int title, part = 0, vts_ttn; int found; int16_t pgcN, pgN; vts_ptt_srpt = vm->vtsi->vts_ptt_srpt; pgcN = get_PGCN(vm); pgN = vm->state.pgN; found = 0; for (vts_ttn = 0; (vts_ttn < vts_ptt_srpt->nr_of_srpts) && !found; vts_ttn++) { for (part = 0; (part < vts_ptt_srpt->title[vts_ttn].nr_of_ptts) && !found; part++) { if (vts_ptt_srpt->title[vts_ttn].ptt[part].pgcn == pgcN) { if (vts_ptt_srpt->title[vts_ttn].ptt[part].pgn == pgN) { found = 1; break; } if (part > 0 && vts_ptt_srpt->title[vts_ttn].ptt[part].pgn > pgN && vts_ptt_srpt->title[vts_ttn].ptt[part - 1].pgn < pgN) { part--; found = 1; break; } } } if (found) break; } vts_ttn++; part++; if (!found) { fprintf(MSG_OUT, "libdvdnav: chapter NOT FOUND!\n"); return 0; } title = get_TT(vm, vm->state.vtsN, vts_ttn);#ifdef TRACE if (title) { fprintf(MSG_OUT, "libdvdnav: ************ this chapter FOUND!\n"); fprintf(MSG_OUT, "libdvdnav: VTS_PTT_SRPT - Title %3i part %3i: PGC: %3i PG: %3i\n", title, part, vts_ptt_srpt->title[vts_ttn-1].ptt[part-1].pgcn , vts_ptt_srpt->title[vts_ttn-1].ptt[part-1].pgn ); }#endif *title_result = title; *part_result = part; return 1;}/* Return the substream id for 'logical' audio stream audioN. * 0 <= audioN < 8 */int vm_get_audio_stream(vm_t *vm, int audioN) { int streamN = -1; if((vm->state).domain != VTS_DOMAIN) audioN = 0; if(audioN < 8) { /* Is there any control info for this logical stream */ if((vm->state).pgc->audio_control[audioN] & (1<<15)) { streamN = ((vm->state).pgc->audio_control[audioN] >> 8) & 0x07; } } if((vm->state).domain != VTS_DOMAIN && streamN == -1) streamN = 0; /* FIXME: Should also check in vtsi/vmgi status what kind of stream * it is (ac3/lpcm/dts/sdds...) to find the right (sub)stream id */ return streamN;}/* Return the substream id for 'logical' subpicture stream subpN and given mode. * 0 <= subpN < 32 * mode == 0 - widescreen * mode == 1 - letterbox * mode == 2 - pan&scan */int vm_get_subp_stream(vm_t *vm, int subpN, int mode) { int streamN = -1; int source_aspect = vm_get_video_aspect(vm); if((vm->state).domain != VTS_DOMAIN) subpN = 0; if(subpN < 32) { /* a valid logical stream */ /* Is this logical stream present */ if((vm->state).pgc->subp_control[subpN] & (1<<31)) { if(source_aspect == 0) /* 4:3 */ streamN = ((vm->state).pgc->subp_control[subpN] >> 24) & 0x1f; if(source_aspect == 3) /* 16:9 */ switch (mode) { case 0: streamN = ((vm->state).pgc->subp_control[subpN] >> 16) & 0x1f; break; case 1: streamN = ((vm->state).pgc->subp_control[subpN] >> 8) & 0x1f; break; case 2: streamN = (vm->state).pgc->subp_control[subpN] & 0x1f; } } } if((vm->state).domain != VTS_DOMAIN && streamN == -1) streamN = 0; /* FIXME: Should also check in vtsi/vmgi status what kind of stream it is. */ return streamN;}int vm_get_audio_active_stream(vm_t *vm) { int audioN; int streamN; audioN = (vm->state).AST_REG ; streamN = vm_get_audio_stream(vm, audioN); /* If no such stream, then select the first one that exists. */ if(streamN == -1) { for(audioN = 0; audioN < 8; audioN++) { if((vm->state).pgc->audio_control[audioN] & (1<<15)) { if ((streamN = vm_get_audio_stream(vm, audioN)) >= 0) break; } } } return streamN;}int vm_get_subp_active_stream(vm_t *vm, int mode) { int subpN; int streamN; subpN = (vm->state).SPST_REG & ~0x40; streamN = vm_get_subp_stream(vm, subpN, mode); /* If no such stream, then select the first one that exists. */ if(streamN == -1) { for(subpN = 0; subpN < 32; subpN++) { if((vm->state).pgc->subp_control[subpN] & (1<<31)) { if ((streamN = vm_get_subp_stream(vm, subpN, mode)) >= 0) break; } } } if((vm->state).domain == VTS_DOMAIN && !((vm->state).SPST_REG & 0x40)) /* Bit 7 set means hide, and only let Forced display show */ return (streamN | 0x80); else return streamN;}void vm_get_angle_info(vm_t *vm, int *current, int *num_avail) { *num_avail = 1; *current = 1; if((vm->state).domain == VTS_DOMAIN) { title_info_t *title; /* TTN_REG does not allways point to the correct title.. */ if((vm->state).TTN_REG > vm->vmgi->tt_srpt->nr_of_srpts) return; title = &vm->vmgi->tt_srpt->title[(vm->state).TTN_REG - 1]; if(title->title_set_nr != (vm->state).vtsN || title->vts_ttn != (vm->state).VTS_TTN_REG) return; *num_avail = title->nr_of_angles; *current = (vm->state).AGL_REG; }}#if 0/* currently unused */void vm_get_audio_info(vm_t *vm, int *current, int *num_avail) { switch ((vm->state).domain) { case VTS_DOMAIN: *num_avail = vm->vtsi->vtsi_mat->nr_of_vts_audio_streams; *current = (vm->state).AST_REG; break; case VTSM_DOMAIN: *num_avail = vm->vtsi->vtsi_mat->nr_of_vtsm_audio_streams; /* 1 */ *current = 1; break; case VMGM_DOMAIN: case FP_DOMAIN: *num_avail = vm->vmgi->vmgi_mat->nr_of_vmgm_audio_streams; /* 1 */ *current = 1; break; }}/* currently unused */void vm_get_subp_info(vm_t *vm, int *current, int *num_avail) { switch ((vm->state).domain) { case VTS_DOMAIN: *num_avail = vm->vtsi->vtsi_mat->nr_of_vts_subp_streams; *current = (vm->state).SPST_REG; break; case VTSM_DOMAIN: *num_avail = vm->vtsi->vtsi_mat->nr_of_vtsm_subp_streams; /* 1 */ *current = 0x41; break; case VMGM_DOMAIN: case FP_DOMAIN: *num_avail = vm->vmgi->vmgi_mat->nr_of_vmgm_subp_streams; /* 1 */ *current = 0x41; break; }}/* currently unused */void vm_get_video_res(vm_t *vm, int *width, int *height) { video_attr_t attr = vm_get_video_attr(vm); if(attr.video_format != 0) *height = 576; else *height = 480; switch(attr.picture_size) { case 0: *width = 720; break; case 1: *width = 704; break; case 2: *width = 352; break; case 3: *width = 352; *height /= 2; break; }}#endifint vm_get_video_aspect(vm_t *vm) { int aspect = vm_get_video_attr(vm).display_aspect_ratio; assert(aspect == 0 || aspect == 3); (vm->state).registers.SPRM[14] &= ~(0x3 << 10); (vm->state).registers.SPRM[14] |= aspect << 10; return aspect;}int vm_get_video_scale_permission(vm_t *vm) { return vm_get_video_attr(vm).permitted_df;}video_attr_t vm_get_video_attr(vm_t *vm) { switch ((vm->state).domain) { case VTS_DOMAIN: return vm->vtsi->vtsi_mat->vts_video_attr; case VTSM_DOMAIN: return vm->vtsi->vtsi_mat->vtsm_video_attr; case VMGM_DOMAIN: case FP_DOMAIN: return vm->vmgi->vmgi_mat->vmgm_video_attr; default: abort(); }}audio_attr_t vm_get_audio_attr(vm_t *vm, int streamN) { switch ((vm->state).domain) { case VTS_DOMAIN: return vm->vtsi->vtsi_mat->vts_audio_attr[streamN]; case VTSM_DOMAIN: return vm->vtsi->vtsi_mat->vtsm_audio_attr; case VMGM_DOMAIN: case FP_DOMAIN: return vm->vmgi->vmgi_mat->vmgm_audio_attr; default: abort(); }}subp_attr_t vm_get_subp_attr(vm_t *vm, int streamN) { switch ((vm->state).domain) { case VTS_DOMAIN: return vm->vtsi->vtsi_mat->vts_subp_attr[streamN]; case VTSM_DOMAIN: return vm->vtsi->vtsi_mat->vtsm_subp_attr; case VMGM_DOMAIN: case FP_DOMAIN: return vm->vmgi->vmgi_mat->vmgm_subp_attr; default: abort(); }}/* Playback control */static link_t play_PGC(vm_t *vm) { link_t link_values; #ifdef TRACE fprintf(MSG_OUT, "libdvdnav: play_PGC:"); if((vm->state).domain != FP_DOMAIN) { fprintf(MSG_OUT, " (vm->state).pgcN (%i)\n", get_PGCN(vm)); } else { fprintf(MSG_OUT, " first_play_pgc\n"); }#endif /* This must be set before the pre-commands are executed because they * might contain a CallSS that will save resume state */ /* FIXME: This may be only a temporary fix for something... */ (vm->state).pgN = 1; (vm->state).cellN = 0; (vm->state).blockN = 0; /* eval -> updates the state and returns either
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -