void AvFormatDecoderDVD::PostProcessTracks(void) { if (!ringBuffer) return; if (!ringBuffer->IsDVD()) return; if (tracks[kTrackTypeAudio].size() > 1) { stable_sort(tracks[kTrackTypeAudio].begin(), tracks[kTrackTypeAudio].end()); sinfo_vec_t::iterator it = tracks[kTrackTypeAudio].begin(); for (; it != tracks[kTrackTypeAudio].end(); ++it) { LOG(VB_PLAYBACK, LOG_INFO, QString("DVD Audio Track Map Stream id #%1, MPEG stream %2") .arg(it->stream_id) .arg(ic->streams[it->av_stream_index]->id)); } int trackNo = ringBuffer->DVD()->GetTrack(kTrackTypeAudio); if (trackNo >= (int)GetTrackCount(kTrackTypeAudio)) trackNo = GetTrackCount(kTrackTypeAudio) - 1; SetTrack(kTrackTypeAudio, trackNo); } if (tracks[kTrackTypeSubtitle].size() > 0) { stable_sort(tracks[kTrackTypeSubtitle].begin(), tracks[kTrackTypeSubtitle].end()); sinfo_vec_t::iterator it = tracks[kTrackTypeSubtitle].begin(); for(; it != tracks[kTrackTypeSubtitle].end(); ++it) { LOG(VB_PLAYBACK, LOG_INFO, QString("DVD Subtitle Track Map Stream id #%1 ") .arg(it->stream_id)); } stable_sort(tracks[kTrackTypeSubtitle].begin(), tracks[kTrackTypeSubtitle].end()); int trackNo = ringBuffer->DVD()->GetTrack(kTrackTypeSubtitle); uint captionmode = m_parent->GetCaptionMode(); int trackcount = (int)GetTrackCount(kTrackTypeSubtitle); if (captionmode == kDisplayAVSubtitle && (trackNo < 0 || trackNo >= trackcount)) { m_parent->EnableSubtitles(false); } else if (trackNo >= 0 && trackNo < trackcount && !ringBuffer->IsInDiscMenuOrStillFrame()) { SetTrack(kTrackTypeSubtitle, trackNo); m_parent->EnableSubtitles(true); } } }
void CDDBQuery::_SetDefaultInfo() { for (int16 i = fCDData.CountTracks(); i >= 0; i--) fCDData.RemoveTrack(i); vector<CDAudioTime> trackTimes; GetTrackTimes(&fSCSIData, trackTimes); int32 trackCount = GetTrackCount(&fSCSIData); fCDData.SetArtist("Artist"); fCDData.SetAlbum("Audio CD"); fCDData.SetGenre("Misc"); for (int32 i = 0; i < trackCount; i++) { BString trackname("Track "); if (i < 9) trackname << "0"; trackname << i + 1; CDAudioTime time = trackTimes[i + 1] - trackTimes[i]; fCDData.AddTrack(trackname.String(), time); } }
int ReAnimEntityWidget::GetTotalHeight() const { int result = 0; if( m_toggleButton->isChecked() ) { result = GetTopPadding() + ( 1 + GetTrackCount() ) * ( ANIM_ENTITY_SUITE_HEIGHT + GetVerticalGap() ); } else { result = GetTopPadding() + GetBottomPadding() + ANIM_ENTITY_SUITE_HEIGHT; } return result; }
void AvFormatDecoderDVD::PostProcessTracks(void) { if (!ringBuffer) return; if (!ringBuffer->IsDVD()) return; if (tracks[kTrackTypeAudio].size() > 1) { stable_sort(tracks[kTrackTypeAudio].begin(), tracks[kTrackTypeAudio].end()); int trackNo = -1; int dvdTrack = ringBuffer->DVD()->GetTrack(kTrackTypeAudio); for (uint i = 0; i < GetTrackCount(kTrackTypeAudio); i++) { LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("DVD Audio Track Map Stream id #%1, av_stream_idx %2, MPEG stream 0x%3, lang %4") .arg(tracks[kTrackTypeAudio][i].stream_id) .arg(tracks[kTrackTypeAudio][i].av_stream_index) .arg(ic->streams[tracks[kTrackTypeAudio][i].av_stream_index]->id,0,16) .arg(iso639_key_toName(tracks[kTrackTypeAudio][i].language))); // Find the audio track in our list that maps to the // selected track in the ringbuffer (the ringbuffer's // list should be in the same order but can have gaps, // so we look for the track with the same index) if (tracks[kTrackTypeAudio][i].stream_id == dvdTrack) trackNo = i; } if (trackNo < 0 && GetTrackCount(kTrackTypeAudio) > 0) { // Take the first track trackNo = 0; } if (trackNo >= 0) SetTrack(kTrackTypeAudio, trackNo); } if (tracks[kTrackTypeSubtitle].size() > 0) { map<int,uint> lang_sub_cnt; map<int,int> stream2idx; // First, create a map containing stream id -> track index // of the subtitle streams that have been found so far. for (uint n = 0; n < GetTrackCount(kTrackTypeSubtitle); n++) { int stream_id = tracks[kTrackTypeSubtitle][n].stream_id & 0x1f; stream2idx[stream_id] = n; } // Get all subtitle tracks from the DVD and filter out any that // are not mapped in the current program chain. sinfo_vec_t filteredTracks; if (!ringBuffer->DVD()->IsInMenu()) { for (uint i = 0; i < 32; ++i) { int streamid = ringBuffer->DVD()->GetSubtitleTrackNum(i); if (streamid >= 0) { // This stream is mapped in the current program chain int lang = ringBuffer->DVD()->GetSubtitleLanguage(i); int lang_indx = lang_sub_cnt[lang]++; int trackNo = -1; if (stream2idx.count(streamid) != 0) trackNo = stream2idx[streamid]; if (trackNo == -1) { // Create a dummy track if the physical stream has not // yet been seen. filteredTracks.push_back(StreamInfo(-1, lang, lang_indx, streamid, 0, 0, false, false, false)); } else { // Otherwise use the real data filteredTracks.push_back(tracks[kTrackTypeSubtitle][trackNo]); filteredTracks.back().stream_id &= 0x1f; filteredTracks.back().language = lang; filteredTracks.back().language_index = lang_indx; } } } } tracks[kTrackTypeSubtitle] = filteredTracks; stable_sort(tracks[kTrackTypeSubtitle].begin(), tracks[kTrackTypeSubtitle].end()); int trackNo = -1; int selectedStream = ringBuffer->DVD()->GetTrack(kTrackTypeSubtitle); // Now iterate over the sorted list and try to find the index of the // currently selected track. for (uint idx = 0; idx < GetTrackCount(kTrackTypeSubtitle); idx++) { const StreamInfo& stream = tracks[kTrackTypeSubtitle][idx]; int avidx = stream.av_stream_index; QString mpegstream; if (avidx >= 0) mpegstream = QString( "0x%1").arg(ic->streams[avidx]->id,0,16); else mpegstream = "n/a"; LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("DVD Subtitle Track Map Stream id #%1, av_stream_idx %2, MPEG #%3, lang %4") .arg(stream.stream_id) .arg(stream.av_stream_index) .arg(mpegstream) .arg(iso639_key_toName(stream.language))); if ((selectedStream != -1) && (stream.stream_id == selectedStream)) trackNo = (int)idx; } uint captionmode = m_parent->GetCaptionMode(); int trackcount = (int)GetTrackCount(kTrackTypeSubtitle); if (captionmode == kDisplayAVSubtitle && (trackNo < 0 || trackNo >= trackcount)) { m_parent->EnableSubtitles(false); } else if (trackNo >= 0 && trackNo < trackcount) { SetTrack(kTrackTypeSubtitle, trackNo); m_parent->EnableSubtitles(true); } } }
status_t CDDBQuery::_ReadFromServer(BString &data) { // This function queries the given CDDB server for the existence of the disc's data and // saves the data to file once obtained. // Query for the existence of the disc in the database char idString[10]; sprintf(idString, "%08lx", fCDData.DiscID()); BString query; int32 trackCount = GetTrackCount(&fSCSIData); BString offsetString = OffsetsToString(&fSCSIData); int32 discLength = (fCDData.DiscTime()->GetMinutes() * 60) + fCDData.DiscTime()->GetSeconds(); query << "cddb query " << idString << ' ' << trackCount << ' ' << offsetString << ' ' << discLength << '\n'; STRACE((">%s", query.String())); if (fSocket.Send(query.String(), query.Length()) == -1) { _Disconnect(); return B_ERROR; } BString tmp; _ReadLine(tmp); STRACE(("<%s", tmp.String())); BString category; BString queryDiscID(idString); if (tmp.FindFirst("200") != 0) { if (tmp.FindFirst("211") == 0) { // A 211 means that the query was not exact. To make sure that we don't // have a problem with this in the future, we will choose the first entry that // the server returns. This may or may not be wise, but in my experience, the first // one has been the right one. _ReadLine(tmp); // Get the category from the what the server returned _GetToken(tmp.String(), category); // Now we will get the disc ID for the CD. We will need this when we query for // the track name list. If we send the track name query with the real discID, nothing // will be returned. However, if we send the one from the entry, we'll get the names // and we can take these names attach them to the disc that we have. _GetToken(tmp.String() + category.CountChars(), queryDiscID); // This is to suck up any more search results that the server sends us. BString throwaway; _ReadLine(throwaway); while (throwaway.ByteAt(0) != '.') _ReadLine(throwaway); } else { // We get here for any time the CDDB server does not recognize the CD, amongst other things STRACE(("CDDB lookup error: %s\n", tmp.String())); fCDData.SetGenre("misc"); return B_NAME_NOT_FOUND; } } else { _GetToken(tmp.String() + 3, category); } STRACE(("CDDBQuery::_ReadFromServer: Genre: %s\n", category.String())); if (!category.Length()) { STRACE(("Set genre to 'misc'\n")); category = "misc"; } // Query for the disc's data - artist, album, tracks, etc. query = ""; query << "cddb read " << category << ' ' << queryDiscID << '\n' ; if (fSocket.Send(query.String(), query.Length()) == -1) { _Disconnect(); return B_ERROR; } while (true) { _ReadLine(tmp); if (tmp == "." || tmp == ".\n") break; data << tmp << '\n'; } return B_OK; }
void CDDBQuery::_ParseData(const BString &data) { // Can't simply call MakeEmpty() because the thread is spawned when the discID kept in fCDData // is not the same as what's in the drive and MakeEmpty invalidates *everything* in the object. // Considering that we reassign everything here, simply emptying the track list should be sufficient for (int16 i = fCDData.CountTracks(); i >= 0; i--) fCDData.RemoveTrack(i); vector<CDAudioTime> trackTimes; GetTrackTimes(&fSCSIData,trackTimes); int32 trackCount = GetTrackCount(&fSCSIData); if (data.CountChars() < 1) { // This case occurs when the CDDB lookup fails. On these occasions, we need to generate // the file ourselves. This is actually pretty easy. fCDData.SetArtist("Artist"); fCDData.SetAlbum("Audio CD"); fCDData.SetGenre("Misc"); for (int32 i = 0; i < trackCount; i++) { BString trackname("Track "); if (i < 9) trackname << "0"; trackname << i + 1; CDAudioTime time = trackTimes[i + 1] - trackTimes[i]; fCDData.AddTrack(trackname.String(), time); } } // TODO: This function is dog slow, but it works. Optimize. // Ideally, the search should be done sequentially using GetLineFromString() and strchr(). // Order: genre(category), frame offsets, disc length, artist/album, track titles int32 pos; pos = data.FindFirst("DYEAR="); if (pos > 0) { BString artist,album; artist = album = GetLineFromString(data.String() + sizeof("DYEAR") + pos); // TODO: finish, once I find an entry which actually has a year in it BAlert *alert = new BAlert("SimplyVorbis", "DYEAR entry found\n", "OK"); alert->Go(); } pos = data.FindFirst("DTITLE="); if (pos > 0) { BString artist,album; artist = album = GetLineFromString(data.String() + sizeof("DTITLE") + pos); pos = artist.FindFirst(" / "); if (pos > 0) artist.Truncate(pos); fCDData.SetArtist(artist.String()); album = album.String() + pos + sizeof(" / ") - 1; fCDData.SetAlbum(album.String()); } BString category = GetLineFromString(data.String() + 4); pos = category.FindFirst(" "); if (pos > 0) category.Truncate(pos); fCDData.SetGenre(category.String()); pos = data.FindFirst("TTITLE0="); if (pos > 0) { int32 trackCount = 0; BString searchString = "TTITLE0="; while (pos > 0) { BString trackName = data.String() + pos + searchString.Length(); trackName.Truncate(trackName.FindFirst("\n")); CDAudioTime tracktime = trackTimes[trackCount + 1] - trackTimes[trackCount]; fCDData.AddTrack(trackName.String(),tracktime); trackCount++; searchString = "TTITLE"; searchString << trackCount << "="; pos = data.FindFirst(searchString.String(),pos); } } }