📄 nav.c
字号:
{ int button; //int width, height; //vm_get_video_res(&width, &height); button = mouse_over_hl(pci, ce->mouse.x, ce->mouse.y); if(button) button_nr = button; else is_action = 0; } break; default: DNOTE("ignoring dvdctrl event (%d)\n", ce->type); break; } /* Must check if the current selected button has auto_action_mode !!! */ /* Don't do auto action if it's been selected with the mouse... ?? */ switch(pci->hli.btnit[button_nr - 1].auto_action_mode) { case 0: break; case 1: if(ce->type == DVDCtrlMouseSelect) { /* auto_action buttons can't be select if they are not activated keep the previous selected button */ button_nr = (*btn_reg) >> 10; } else { DNOTE("%s", "auto_action_mode set!\n"); is_action = 1; } break; case 2: case 3: default: FATAL("send bug report, unknown auto_action_mode(%d) btn: %d\n", pci->hli.btnit[button_nr - 1].auto_action_mode, button_nr); navPrint_PCI(pci); exit(1); } /* If a new button has been selected or if one has been activated. */ /* Determine the correct area and send the information to the spu decoder. */ /* Don't send if its the same as last time. */ if(is_action || button_nr != ((*btn_reg) >> 10)) { btni_t *button; button = &pci->hli.btnit[button_nr - 1]; send_highlight(button->x_start, button->y_start, button->x_end, button->y_end, pci->hli.btn_colit.btn_coli[button->btn_coln-1][is_action]); } /* Write the (updated) value back to the button register. */ *btn_reg = button_nr << 10; return is_action;}/** * Update the highligted button in response to a new pci packet. * Also send highlight information to the spu_mixer. * * @return One if the (possibly updated) button is activated. * Zero otherwise. */static void process_pci(pci_t *pci, uint16_t *btn_reg) { /* Keep the button register value in a local variable. */ uint16_t button_nr = (*btn_reg) >> 10; /* Check if this is alright, i.e. pci->hli.hl_gi.hli_ss == 1 only * for the first menu pic packet? Should be. * What about looping menus? Will reset it every loop.. */ if(pci->hli.hl_gi.hli_ss == 1) { if(pci->hli.hl_gi.fosl_btnn != 0) { button_nr = pci->hli.hl_gi.fosl_btnn; DNOTE("forced select button %d\n", pci->hli.hl_gi.fosl_btnn); } } /* SPRM[8] can be changed by A) user operations user operations can only change SPRM[8] if buttons exist. B) navigation commands navigation commands can change SPRM[8] always. C) highlight information if no buttons exist SPRM[8] is kept at it's value (except when navigation commands change it) if SPRM[8] doesn't have a valid value (button_nr > nr_buttons) button_nr = nr_buttons (except when nr_buttons == 0, then button_nr isn't changed at all. */ if((pci->hli.hl_gi.hli_ss & 0x03) != 0 && button_nr > pci->hli.hl_gi.btn_ns && pci->hli.hl_gi.btn_ns != 0) { button_nr = pci->hli.hl_gi.btn_ns; } /* Determine the correct highlight and send the information to the spu. */ if((pci->hli.hl_gi.hli_ss & 0x03) == 0 || button_nr > pci->hli.hl_gi.btn_ns) { /* Turn off the highlight. */ send_highlight(0, 0, 0, 0, 0 /* Transparent */); } else { /* Possible optimization: don't send if its the same as last time. As in same hli info, same button number and same select/action state. */ btni_t *button = &pci->hli.btnit[button_nr - 1]; send_highlight(button->x_start, button->y_start, button->x_end, button->y_end, pci->hli.btn_colit.btn_coli[button->btn_coln-1][0]); } /* Write the (updated) value back to the button register. */ *btn_reg = button_nr << 10;}int process_seek(int seconds, dsi_t *dsi, cell_playback_t *cell){ int res = 0; dvd_time_t current_time; // bit 0: v0: *Video data* does not exist in the VOBU at the address// v1: *video data* does exists in the VOBU on the address// bit 1: indicates whether theres *video data* between // current vobu and last vobu. ??// if address = 3fff ffff -> vobu does not exist#define VALID_XWDA(OFFSET) \ (((OFFSET) & SRI_END_OF_CELL) != SRI_END_OF_CELL && \ ((OFFSET) & 0x80000000)) vm_get_current_time(¤t_time, &(dsi->dsi_gi.c_eltm)); // Try using the Time Map Tables, should we use VOBU seeks for // small seek (< 8s) anyway? as they (may) have better resolution. // Fall back if we're crossing a cell bounduary... if(vm_time_play(¤t_time, seconds)) { return 1; // Successfull } else { // We have 120 60 30 10 7.5 7 6.5 ... 0.5 seconds markers if(seconds > 0) { const unsigned int time[19] = { 240, 120, 60, 20, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1}; const unsigned int hsec = seconds * 2; unsigned int diff, idx = 0; diff = abs(hsec - time[0]); while(idx < 19 && abs(hsec - time[idx]) <= diff) { diff = abs(hsec - time[idx]); idx++; } idx--; // Restore it to the one that got us the diff // Make sure we have a VOBU that 'exists' (with in the cell) // What about the 'top' two bits here? If there is no video at the // seek destination? Check with the menus in Coruptor. while(idx < 19 && !VALID_XWDA(dsi->vobu_sri.fwda[idx])) { idx++; } if(idx < 19) { // Fake this, as a jump with blockN as destination // blockN is relative the start of the cell state.blockN = dsi->dsi_gi.nv_pck_lbn + (dsi->vobu_sri.fwda[idx] & 0x3fffffff) - cell->first_sector; res = 1; } else res = 0; // no new block found.. must be at the end of the cell.. } else { const unsigned int time[19] = { 240, 120, 60, 20, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1}; const unsigned int hsec = (-seconds) * 2; // - unsigned int diff, idx = 0; diff = abs(hsec - time[0]); while(idx < 19 && abs(hsec - time[idx]) <= diff) { diff = abs(hsec - time[idx]); idx++; } idx--; // Restore it to the one that got us the diff // Make sure we have a VOBU that 'exicsts' (with in the cell) // What about the 'top' two bits here? If there is no video at the // seek destination? Check with the menus in Coruptor. while(idx < 19 && !VALID_XWDA(dsi->vobu_sri.bwda[18-idx])) { idx++; } if(idx < 19) { // Fake this, as a jump with blockN as destination // blockN is relative the start of the cell state.blockN = dsi->dsi_gi.nv_pck_lbn - (dsi->vobu_sri.bwda[18-idx] & 0x3fffffff) - cell->first_sector; res = 1; } else res = 0; // no new_block found.. must be at the end of the cell.. } } return res;}/* Do user input processing. Like audio change, * subpicture change and answer attribute query requests. * access menus, pause, play, jump forward/backward... */int process_user_data(MsgEvent_t ev, pci_t *pci, dsi_t *dsi, cell_playback_t *cell, int block, int *still_time){ int res = 0; //fprintf(stderr, "nav: User input, MsgEvent.type: %d\n", ev.type); switch(ev.dvdctrl.cmd.type) { case DVDCtrlLeftButtonSelect: case DVDCtrlRightButtonSelect: case DVDCtrlUpperButtonSelect: case DVDCtrlLowerButtonSelect: case DVDCtrlButtonActivate: case DVDCtrlButtonSelect: case DVDCtrlButtonSelectAndActivate: case DVDCtrlMouseSelect: case DVDCtrlMouseActivate: // A button has already been activated, discard this event?? if(cell->first_sector <= pci->pci_gi.nv_pck_lbn && cell->last_vobu_start_sector >= pci->pci_gi.nv_pck_lbn) { /* Update selected/activated button, send highlight info to spu */ /* Returns true if a button is activated */ if(process_button(&ev.dvdctrl.cmd, pci, &state.HL_BTNN_REG)) { int button_nr = state.HL_BTNN_REG >> 10; res = vm_eval_cmd(&pci->hli.btnit[button_nr - 1].cmd); } } break; case DVDCtrlTimeSkip: if(dsi->dsi_gi.nv_pck_lbn == -1) { // we are waiting for a new nav block res = 0; break; } res = process_seek(ev.dvdctrl.cmd.timeskip.seconds, dsi, cell); if(res) NOTE("%s", "Doing time seek\n"); break; case DVDCtrlMenuCall: NOTE("Jumping to Menu %d\n", ev.dvdctrl.cmd.menucall.menuid); res = vm_menu_call(ev.dvdctrl.cmd.menucall.menuid, block); if(!res) NOTE("%s", "No such menu!\n"); break; case DVDCtrlResume: res = vm_resume(); break; case DVDCtrlGoUp: res = vm_goup_pgc(); break; case DVDCtrlBackwardScan: DNOTE("unknown (not handled) DVDCtrlEvent %d\n", ev.dvdctrl.cmd.type); break; case DVDCtrlPauseOn: case DVDCtrlPauseOff: case DVDCtrlForwardScan: { MsgEvent_t send_ev; static double last_speed = 1.0; send_ev.type = MsgEventQSpeed; if(ev.dvdctrl.cmd.type == DVDCtrlForwardScan) { send_ev.speed.speed = ev.dvdctrl.cmd.scan.speed; last_speed = ev.dvdctrl.cmd.scan.speed; } /* Perhaps we should remeber the speed before the pause. */ else if(ev.dvdctrl.cmd.type == DVDCtrlPauseOn) send_ev.speed.speed = 0.000000001; else if(ev.dvdctrl.cmd.type == DVDCtrlPauseOff) send_ev.speed.speed = last_speed; /* Hack to exit STILL_MODE if we're in it. */ if(cell->first_sector + block > cell->last_vobu_start_sector && *still_time > 0) { *still_time = 0; } MsgSendEvent(msgq, CLIENT_RESOURCE_MANAGER, &send_ev, 0); } break; case DVDCtrlNextPGSearch: res = vm_next_pg(); break; case DVDCtrlPrevPGSearch: res = vm_prev_pg(); break; case DVDCtrlTopPGSearch: res = vm_top_pg(); break; case DVDCtrlPTTSearch: res = vm_jump_ptt(ev.dvdctrl.cmd.pttsearch.ptt); break; case DVDCtrlPTTPlay: res = vm_jump_title_ptt(ev.dvdctrl.cmd.pttplay.title, ev.dvdctrl.cmd.pttplay.ptt); break; case DVDCtrlTitlePlay: res = vm_jump_title(ev.dvdctrl.cmd.titleplay.title); break; case DVDCtrlTimeSearch: // not in One_Random_PGC_Title or Multi_PGC_Title //dsi.dsi_gi.c_eltm; /* Current 'nav' time */ //ev.dvdctrl.cmd.timesearch.time; /* wanted time */ //dsi.vobu_sri.[FWDA|BWDA]; /* Table for small searches */ break; case DVDCtrlTimePlay: // not in One_Random_PGC_Title or Multi_PGC_Title DNOTE("unknown (not handled) DVDCtrlEvent %d\n", ev.dvdctrl.cmd.type); break; case DVDCtrlStop: DNOTE("unknown (not handled) DVDCtrlEvent %d\n", ev.dvdctrl.cmd.type); break; case DVDCtrlAngleChange: /* FIXME $$$ need to actually change the playback angle too, no? */ state.AGL_REG = ev.dvdctrl.cmd.anglechange.anglenr; break; case DVDCtrlAudioStreamChange: // FIXME $$$ Temorary hack state.AST_REG = ev.dvdctrl.cmd.audiostreamchange.streamnr; // XXX break; case DVDCtrlSubpictureStreamChange: // FIXME $$$ Temorary hack state.SPST_REG &= 0x40; // Keep the on/off bit. state.SPST_REG |= ev.dvdctrl.cmd.subpicturestreamchange.streamnr; NOTE("DVDCtrlSubpictureStreamChange %x\n", state.SPST_REG); break; case DVDCtrlSetSubpictureState: if(ev.dvdctrl.cmd.subpicturestate.display == DVDTrue) state.SPST_REG |= 0x40; // Turn it on else state.SPST_REG &= ~0x40; // Turn it off NOTE("DVDCtrlSetSubpictureState 0x%x\n", state.SPST_REG); break; case DVDCtrlGetCurrentDomain: { MsgEvent_t send_ev; int domain; domain = vm_get_domain(); send_ev.type = MsgEventQDVDCtrl; send_ev.dvdctrl.cmd.type = DVDCtrlCurrentDomain; send_ev.dvdctrl.cmd.domain.domain = domain; MsgSendEvent(msgq, ev.any.client, &send_ev, 0); } break; case DVDCtrlGetCurrentLocation: { MsgEvent_t send_ev; dvd_time_t current_time; dvd_time_t total_time; DVDLocation_t *location; send_ev.type = MsgEventQDVDCtrl; send_ev.dvdctrl.cmd.type = DVDCtrlCurrentLocation; /* should not return when domain is wrong( /= title). */ /* how to get current time for searches in menu/system space? */ /* a bit of a hack */ location = &send_ev.dvdctrl.cmd.location.location; location->title = state.TTN_REG; location->ptt = state.PTTN_REG; vm_get_total_time(&total_time); time_convert(&location->title_total, &total_time); vm_get_current_time(¤t_time, &(pci->pci_gi.e_eltm)); time_convert(&location->title_current, ¤t_time); MsgSendEvent(msgq, ev.any.client, &send_ev, 0); } break; case DVDCtrlGetDVDVolumeInfo: { int nofv,vol,side,noft; MsgEvent_t send_ev; send_ev.type = MsgEventQDVDCtrl; send_ev.dvdctrl.cmd.type = DVDCtrlDVDVolumeInfo; vm_get_volume_info(&nofv,&vol,&side,&noft); send_ev.dvdctrl.cmd.volumeinfo.volumeinfo.nrofvolumes = nofv; send_ev.dvdctrl.cmd.volumeinfo.volumeinfo.volume = vol; send_ev.dvdctrl.cmd.volumeinfo.volumeinfo.side = side; send_ev.dvdctrl.cmd.volumeinfo.volumeinfo.nroftitles = noft; MsgSendEvent(msgq, ev.any.client, &send_ev, 0); } break; case DVDCtrlGetTitles: { MsgEvent_t send_ev; int titles; titles = vm_get_titles(); send_ev.type = MsgEventQDVDCtrl; send_ev.dvdctrl.cmd.type = DVDCtrlTitles; send_ev.dvdctrl.cmd.titles.titles = titles; MsgSendEvent(msgq, ev.any.client, &send_ev, 0); } break; case DVDCtrlGetNumberOfPTTs: { MsgEvent_t send_ev; int ptts, title; title = ev.dvdctrl.cmd.parts.title; ptts = vm_get_ptts_for_title(title); send_ev.type = MsgEventQDVDCtrl; send_ev.dvdctrl.cmd.type = DVDCtrlNumberOfPTTs; send_ev.dvdctrl.cmd.parts.title = title; send_ev.dvdctrl.cmd.parts.ptts = ptts; MsgSendEvent(msgq, ev.any.client, &send_ev, 0); } break; case DVDCtrlGetCurrentAudio: { MsgEvent_t send_ev; int nS, cS; vm_get_audio_info(&nS, &cS); send_ev.type = MsgEventQDVDCtrl; send_ev.dvdctrl.cmd.type = DVDCtrlCurrentAudio; send_ev.dvdctrl.cmd.currentaudio.nrofstreams = nS; send_ev.dvdctrl.cmd.currentaudio.currentstream = cS; MsgSendEvent(msgq, ev.any.client, &send_ev, 0); } break; case DVDCtrlIsAudioStreamEnabled: { MsgEvent_t send_ev; int streamN = ev.dvdctrl.cmd.audiostreamenabled.streamnr; send_ev.type = MsgEventQDVDCtrl; send_ev.dvdctrl.cmd.type = DVDCtrlAudioStreamEnabled; send_ev.dvdctrl.cmd.audiostreamenabled.streamnr = streamN; send_ev.dvdctrl.cmd.audiostreamenabled.enabled = (vm_get_audio_stream(streamN) != -1) ? DVDTrue : DVDFalse; MsgSendEvent(msgq, ev.any.client, &send_ev, 0); } break; case DVDCtrlGetCurrentUOPS: // FIXME XXX $$$ Not done { DVDUOP_t res = 0; MsgEvent_t send_ev; send_ev.type = MsgEventQDVDCtrl; send_ev.dvdctrl.cmd.currentuops.type = DVDCtrlCurrentUOPS; { user_ops_t p_uops = vm_get_uops(); /* This mess is needed... * becuse we didn't do a endian swap in libdvdread */ res |= (p_uops.title_or_time_play ? 0 : UOP_FLAG_TitleOrTimePlay); res |= (p_uops.chapter_search_or_play ? 0 : UOP_FLAG_ChapterSearchOrPlay); res |= (p_uops.title_play ? 0 : UOP_FLAG_TitlePlay); res |= (p_uops.stop ? 0 : UOP_FLAG_Stop);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -