⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 nav.c

📁 基于linux的DVD播放器程序
💻 C
📖 第 1 页 / 共 3 页
字号:
    {      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(&current_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(&current_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(&current_time, &(pci->pci_gi.e_eltm));      time_convert(&location->title_current, &current_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 + -