📄 nav.c
字号:
res |= (p_uops.go_up ? 0 : UOP_FLAG_GoUp); res |= (p_uops.time_or_chapter_search ? 0 : UOP_FLAG_TimeOrChapterSearch); res |= (p_uops.prev_or_top_pg_search ? 0 : UOP_FLAG_PrevOrTopPGSearch); res |= (p_uops.next_pg_search ? 0 : UOP_FLAG_NextPGSearch); res |= (p_uops.title_menu_call ? 0 : UOP_FLAG_TitleMenuCall); res |= (p_uops.root_menu_call ? 0 : UOP_FLAG_RootMenuCall); res |= (p_uops.subpic_menu_call ? 0 : UOP_FLAG_SubPicMenuCall); res |= (p_uops.audio_menu_call ? 0 : UOP_FLAG_AudioMenuCall); res |= (p_uops.angle_menu_call ? 0 : UOP_FLAG_AngleMenuCall); res |= (p_uops.chapter_menu_call ? 0 : UOP_FLAG_ChapterMenuCall); res |= (p_uops.resume ? 0 : UOP_FLAG_Resume); res |= (p_uops.button_select_or_activate ? 0 : UOP_FLAG_ButtonSelectOrActivate); res |= (p_uops.still_off ? 0 : UOP_FLAG_StillOff); res |= (p_uops.pause_on ? 0 : UOP_FLAG_PauseOn); res |= (p_uops.audio_stream_change ? 0 : UOP_FLAG_AudioStreamChange); res |= (p_uops.subpic_stream_change ? 0 : UOP_FLAG_SubPicStreamChange); res |= (p_uops.angle_change ? 0 : UOP_FLAG_AngleChange); res |= (p_uops.karaoke_audio_pres_mode_change ? 0 : UOP_FLAG_KaraokeAudioPresModeChange); res |= (p_uops.video_pres_mode_change ? 0 : UOP_FLAG_VideoPresModeChange); } send_ev.dvdctrl.cmd.currentuops.uops = res; MsgSendEvent(msgq, ev.any.client, &send_ev, 0); } break; case DVDCtrlGetAudioAttributes: // FIXME XXX $$$ Not done { MsgEvent_t send_ev; int streamN = ev.dvdctrl.cmd.audioattributes.streamnr; send_ev.type = MsgEventQDVDCtrl; send_ev.dvdctrl.cmd.type = DVDCtrlAudioAttributes; send_ev.dvdctrl.cmd.audioattributes.streamnr = streamN; { DVDAudioFormat_t af = DVD_AUDIO_FORMAT_Other; audio_attr_t attr = vm_get_audio_attr(streamN); memset(&send_ev.dvdctrl.cmd.audioattributes.attr, 0, sizeof(DVDAudioAttributes_t)); //TBD switch(attr.audio_format) { case 0: af = DVD_AUDIO_FORMAT_AC3; break; case 2: af = DVD_AUDIO_FORMAT_MPEG1; break; case 3: af = DVD_AUDIO_FORMAT_MPEG2; break; case 4: af = DVD_AUDIO_FORMAT_LPCM; break; case 6: af = DVD_AUDIO_FORMAT_DTS; break; default: NOTE("please send a bug report, unknown Audio format %d!", attr.audio_format); break; } send_ev.dvdctrl.cmd.audioattributes.attr.AudioFormat = af; send_ev.dvdctrl.cmd.audioattributes.attr.AppMode = attr.application_mode; send_ev.dvdctrl.cmd.audioattributes.attr.LanguageExtension = attr.lang_extension; send_ev.dvdctrl.cmd.audioattributes.attr.Language = attr.lang_code; } MsgSendEvent(msgq, ev.any.client, &send_ev, 0); } break; case DVDCtrlGetCurrentSubpicture: { MsgEvent_t send_ev; int nS, cS; vm_get_subp_info(&nS, &cS); send_ev.type = MsgEventQDVDCtrl; send_ev.dvdctrl.cmd.type = DVDCtrlCurrentSubpicture; send_ev.dvdctrl.cmd.currentsubpicture.nrofstreams = nS; send_ev.dvdctrl.cmd.currentsubpicture.currentstream = cS & ~0x40; send_ev.dvdctrl.cmd.currentsubpicture.display = (cS & 0x40) ? DVDTrue : DVDFalse; MsgSendEvent(msgq, ev.any.client, &send_ev, 0); } break; case DVDCtrlIsSubpictureStreamEnabled: { MsgEvent_t send_ev; int streamN = ev.dvdctrl.cmd.subpicturestreamenabled.streamnr; send_ev.type = MsgEventQDVDCtrl; send_ev.dvdctrl.cmd.type = DVDCtrlSubpictureStreamEnabled; send_ev.dvdctrl.cmd.subpicturestreamenabled.streamnr = streamN; send_ev.dvdctrl.cmd.subpicturestreamenabled.enabled = (vm_get_subp_stream(streamN) != -1) ? DVDTrue : DVDFalse; MsgSendEvent(msgq, ev.any.client, &send_ev, 0); } break; case DVDCtrlGetSubpictureAttributes: // FIXME XXX $$$ Not done { MsgEvent_t send_ev; int streamN = ev.dvdctrl.cmd.subpictureattributes.streamnr; send_ev.type = MsgEventQDVDCtrl; send_ev.dvdctrl.cmd.type = DVDCtrlSubpictureAttributes; send_ev.dvdctrl.cmd.subpictureattributes.streamnr = streamN; { subp_attr_t attr = vm_get_subp_attr(streamN); memset(&send_ev.dvdctrl.cmd.subpictureattributes.attr, 0, sizeof(DVDSubpictureAttributes_t)); //TBD send_ev.dvdctrl.cmd.subpictureattributes.attr.Language = attr.lang_code; } MsgSendEvent(msgq, ev.any.client, &send_ev, 0); } break; case DVDCtrlGetCurrentAngle: { MsgEvent_t send_ev; int nS, cS; vm_get_angle_info(&nS, &cS); send_ev.type = MsgEventQDVDCtrl; send_ev.dvdctrl.cmd.type = DVDCtrlCurrentAngle; send_ev.dvdctrl.cmd.currentangle.anglesavailable = nS; send_ev.dvdctrl.cmd.currentangle.anglenr = cS; MsgSendEvent(msgq, ev.any.client, &send_ev, 0); } break; case DVDCtrlGetState: { MsgEvent_t send_ev; char *state_str; DVDCtrlLongStateEvent_t *state_ev; state_str = vm_get_state_str(block); send_ev.type = MsgEventQDVDCtrlLong; send_ev.dvdctrllong.cmd.type = DVDCtrlLongState; state_ev = &(send_ev.dvdctrllong.cmd.state); if(state_str != NULL) { strncpy(state_ev->xmlstr, state_str, sizeof(state_ev->xmlstr)); state_ev->xmlstr[sizeof(state_ev->xmlstr)-1] = '\0'; } else { state_ev->xmlstr[0] = '\0'; } MsgSendEvent(msgq, ev.any.client, &send_ev, 0); free(state_str); } break; case DVDCtrlGetDiscID: { MsgEvent_t send_ev; send_ev.type = MsgEventQDVDCtrl; send_ev.dvdctrl.cmd.type = DVDCtrlDiscID; memcpy(send_ev.dvdctrl.cmd.discid.id, discid, sizeof(discid)); MsgSendEvent(msgq, ev.any.client, &send_ev, 0); } break; case DVDCtrlGetVolIds: { MsgEvent_t send_ev; int voltype; DVDCtrlLongVolIdsEvent_t *ids; send_ev.type = MsgEventQDVDCtrlLong; send_ev.dvdctrllong.cmd.type = DVDCtrlLongVolIds; ids = &(send_ev.dvdctrllong.cmd.volids); voltype = ev.dvdctrl.cmd.volids.voltype; ids->voltype = 0; if(voltype == 0) { if(vm_get_udf_volids(ids->volid, sizeof(ids->volid), ids->volsetid, sizeof(ids->volsetid)) == 0) { ids->voltype = 1; } else if(vm_get_iso_volids(ids->volid, sizeof(ids->volid), ids->volsetid, sizeof(ids->volsetid)) == 0) { ids->voltype = 2; } } else if(voltype == 1) { if(vm_get_udf_volids(ids->volid, sizeof(ids->volid), ids->volsetid, sizeof(ids->volsetid)) == 0) { ids->voltype = 1; } } else if(voltype == 2) { if(vm_get_iso_volids(ids->volid, sizeof(ids->volid), ids->volsetid, sizeof(ids->volsetid)) == 0) { ids->voltype = 2; } } MsgSendEvent(msgq, ev.any.client, &send_ev, 0); } break; default: DNOTE("unknown (not handled) DVDCtrlEvent %d\n", ev.dvdctrl.cmd.type); break; } return res;}int process_long_user_data(MsgEvent_t ev, pci_t *pci, 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.dvdctrllong.cmd.type) { case DVDCtrlLongSetState: res = vm_set_state_str(ev.dvdctrllong.cmd.state.xmlstr); break; default: DNOTE("unknown (not handled) DVDCtrlLongEvent %d\n", ev.dvdctrllong.cmd.type); break; } return res;}static int block;static int still_time;static cell_playback_t *cell;static int pending_lbn;#define INF_STILL_TIME (10 * 0xff)static void do_init_cell(int flush) { cell = &state.pgc->cell_playback[state.cellN - 1]; still_time = 10 * cell->still_time; block = state.blockN; assert(cell->first_sector + block <= cell->last_vobu_start_sector); // FIXME XXX $$$ Only send when needed, and do send even if not playing // from start? (should we do pre_commands when jumping to say part 3?) /* Send the palette to the spu. */ send_spu_palette(state.pgc->palette); /* Get the pci/dsi data */ if(flush) send_demux_sectors(cell->first_sector + block, 1, FlowCtrlFlush); else send_demux_sectors(cell->first_sector + block, 1, FlowCtrlNone); pending_lbn = cell->first_sector + block;}static void do_run(void) { pci_t pci; dsi_t dsi; vm_start(); // see hack in main do_init_cell(0); pci.pci_gi.nv_pck_lbn = -1; dsi.dsi_gi.nv_pck_lbn = -1; while(1) { MsgEvent_t ev; int got_data; // For now.. later use the time instead.. /* Have we read the last dsi packet we asked for? Then request the next. */ if(pending_lbn == dsi.dsi_gi.nv_pck_lbn && cell->first_sector + block <= cell->last_vobu_start_sector) { int complete_video; /* If there is video data in this vobu, but not in the next. Then this data must be a complete image, so let the decoder know this. */ if((dsi.vobu_sri.next_vobu & 0x80000000) == 0 && dsi.dsi_gi.vobu_1stref_ea != 0 /* there is video in this */) { complete_video = FlowCtrlCompleteVideoUnit; //DNOTE("FlowCtrlCompleteVideoUnit = 1;\n"); } else { complete_video = FlowCtrlNone; } /* Demux/play the content of this vobu. */ if(dsi.dsi_gi.vobu_ea != 0) { send_demux_sectors(cell->first_sector + block + 1, dsi.dsi_gi.vobu_ea, complete_video); } /* VOBU still ? */ /* if(cell->playback_mode) .. */ /* need to defer the playing of the next VOBU untill the still * is interrupted. */ /* start - get_next_vobu() */ /* The next vobu is where... (make this a function?) */ /* angle change points are at next ILVU, not sure if one VOBU = one ILVU */ if(0 /*angle && change_angle*/) { /* if( seamless ) else // non seamless */ ; } else { /* .. top two bits are flags */ block += dsi.vobu_sri.next_vobu & 0x3fffffff; } /* TODO XXX $$$ Test earlier and merge the requests if posible? */ /* If there is more data in this cell to demux, then get the * next nav pack. */ if(cell->first_sector + block <= cell->last_vobu_start_sector) { send_demux_sectors(cell->first_sector + block, 1, FlowCtrlNone); pending_lbn = cell->first_sector + block; } else { //DNOTE("end of cell\n"); ; // end of cell! if(still_time == INF_STILL_TIME) // Inf. still time NOTE("%s", "Still picture select an item to continue.\n"); else if(still_time != 0) NOTE("Pause for %d seconds,\n", still_time/10);#if 0 /* TODO XXX $$$ This should only be done at the correct time */ /* Handle forced activate button here */ if(pci.hli.hl_gi.foac_btnn != 0 && (pci.hli.hl_gi.hli_ss & 0x03) != 0) { uint16_t button_nr = state.HL_BTNN_REG >> 10; /* Forced action 0x3f means selected button, otherwise use the specified button */ if(pci.hli.hl_gi.foac_btnn != 0x3f) button_nr = pci.hli.hl_gi.foac_btnn; if(button_nr > pci.hli.hl_gi.btn_ns) ; // error selected but out of range... state.HL_BTNN_REG = button_nr << 10; if(vm_eval_cmd(&pci.hli.btnit[button_nr - 1].cmd)) { do_init_cell(/* ?? */ 0); dsi.dsi_gi.nv_pck_lbn = -1; } }#endif } } // Wait for data/input or for cell still time to end { if(cell->first_sector + block <= cell->last_vobu_start_sector) { got_data = wait_q(msgq, &ev); // Wait for a data packet or a message } else { /* Handle cell still time here */ got_data = 0; if(still_time == INF_STILL_TIME) // Inf. still time MsgNextEvent(msgq, &ev); else while(still_time && MsgCheckEvent(msgq, &ev)) { struct timespec req = {0, 100000000}; // 0.1s nanosleep(&req, NULL); still_time--; } if(!still_time) // No more still time (or there never was any..) if(MsgCheckEvent(msgq, &ev)) { // and no more messages // Let the vm run and give us a new cell to play vm_get_next_cell(); do_init_cell(/* No jump */ 0); dsi.dsi_gi.nv_pck_lbn = -1; } } } /* If we are here we either have a message or an available data packet */ /* User input events */ if(!got_data) { // Then it must be a message (or error?) int res = 0; switch(ev.type) { case MsgEventQDVDCtrl: /* Do user input processing. Like audio change, * subpicture change and answer attribute query requests. * access menus, pause, play, jump forward/backward... */ res = process_user_data(ev, &pci, &dsi, cell, block, &still_time); break; case MsgEventQDVDCtrlLong: res = process_long_user_data(ev, &pci, cell, block, &still_time); break; default: handle_events(msgq, &ev); /* If( new dvdroot ) { vm_reset(get_dvdroot()); block = 0; res = 1; } */ } if(res != 0) {/* a jump has occured */ do_init_cell(/* Flush streams */1); dsi.dsi_gi.nv_pck_lbn = -1; } } else { // We got a data to read. unsigned char buffer[2048]; int len; len = get_q(msgq, &buffer[0]); if(buffer[0] == PS2_PCI_SUBSTREAM_ID) { navRead_PCI(&pci, &buffer[1]); /* Is this the packet we are waiting for? */ if(pci.pci_gi.nv_pck_lbn != pending_lbn) { //fprintf(stdout, "nav: Droped PCI packet\n"); pci.pci_gi.nv_pck_lbn = -1; continue; } //fprintf(stdout, "nav: Got PCI packet\n"); /* if(pci.hli.hl_gi.hli_ss & 0x03) { fprintf(stdout, "nav: Menu detected\n"); navPrint_PCI(&pci); } */ /* Evaluate and Instantiate the new pci packet */ process_pci(&pci, &state.HL_BTNN_REG); } else if(buffer[0] == PS2_DSI_SUBSTREAM_ID) { navRead_DSI(&dsi, &buffer[1]); if(dsi.dsi_gi.nv_pck_lbn != pending_lbn) { //fprintf(stdout, "nav: Droped DSI packet\n"); dsi.dsi_gi.nv_pck_lbn = -1; continue; } //fprintf(stdout, "nav: Got DSI packet\n"); //navPrint_DSI(&dsi); } else { int i; ERROR("Unknown NAV packet type (%02x)\n", buffer[0]); for(i=0;i<20;i++) printf("%02x ", buffer[i]); } } }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -