void PurchaseContestRequestWrapper::updateContestants() { auto target = request.getRequest().initContestants().initEntries(m_contestants.count()); for (uint i = 0; i < target.size(); ++i) { auto contestant = m_contestants.get(i).value<QObject*>(); target[i].setKey(convertText(contestant->property("name").toString())); target[i].setValue(convertText(contestant->property("description").toString())); } }
void MyComboBox::pushBack(Glib::ustring text, double value, bool select) { Gtk::TreeModel::Row row = *refTreeModel->children().begin(); bool find = false; while (row) { if (row[columnsModel.textValue] == text) { find = true; break; } row++; } if (find == false) { row = *(refTreeModel->append()); row[columnsModel.colText] = convertText(text); row[columnsModel.textValue] = text; //row[columnsModel.colText] = text; //row[columnsModel.textValue] = convertText(text); row[columnsModel.colId] = number; row[columnsModel.doubleVlaue] = value; number++; } if (select) { comboBox->set_active(*row); } }
void SurfaceImpl::MeasureWidths(Font &font_, const char *s, int len, int *positions) { QFontMetrics fm = metrics(font_); QString qs = convertText(s, len); // The position for each byte of a character is the offset from the start // where the following character should be drawn. int i_byte = 0, width = 0; for (int i_char = 0; i_char < qs.length(); ++i_char) { width += fm.width(qs.at(i_char)); if (unicodeMode) { // Set the same position for each byte of the character. int nbytes = qs.mid(i_char, 1).utf8().length(); while (nbytes--) positions[i_byte++] = width; } else positions[i_byte++] = width; } }
void SurfaceImpl::MeasureWidths(Font &font_, const char *s, int len, XYPOSITION *positions) { QString qs = convertText(s, len); QTextLayout text_layout(qs, convertQFont(font_), pd); text_layout.beginLayout(); QTextLine text_line = text_layout.createLine(); text_layout.endLayout(); if (unicodeMode) { int i_char = 0, i_byte = 0;; while (i_char < qs.size()) { unsigned char byte = s[i_byte]; int nbytes, code_units; // Work out character sizes by looking at the byte stream. if (byte >= 0xf0) { nbytes = 4; code_units = 2; } else { if (byte >= 0xe0) nbytes = 3; else if (byte >= 0x80) nbytes = 2; else nbytes = 1; code_units = 1; } XYPOSITION position = text_line.cursorToX(i_char + code_units); // Set the same position for each byte of the character. for (int i = 0; i < nbytes && i_byte < len; ++i) positions[i_byte++] = position; i_char += code_units; } // This shouldn't be necessary... XYPOSITION last_position = ((i_byte > 0) ? positions[i_byte - 1] : 0); while (i_byte < len) positions[i_byte++] = last_position; } else { for (int i = 0; i < len; ++i) positions[i] = text_line.cursorToX(i + 1); } }
void StatisticsDialog::slotButtonClicked(int button) { if (button == User1 || button == User2) { KILE_DEBUG() << "Open tab is" << currentPage()->name() << ' ' + (m_pagetoname.contains(currentPage()) ? m_pagetoname[currentPage()] : "No such entry"); QClipboard *clip = KApplication::clipboard(); QString text; convertText(&text, button == User2); clip->setText(text, QClipboard::Selection); // the text will be available with the middle mouse button } KDialog::slotButtonClicked(button); }
void SurfaceImpl::drawText(const PRectangle &rc, Font &font_, XYPOSITION ybase, const char *s, int len, ColourDesired fore) { QString qs = convertText(s, len); QFont *f = PFont(font_.GetID()); if (f) painter->setFont(*f); painter->setPen(convertQColor(fore)); painter->drawText(QPointF(rc.left, ybase), qs); }
void SurfaceImpl::drawText(PRectangle rc, Font &font_, int ybase, const char *s, int len, ColourAllocated fore) { QString qs = convertText(s, len); QFont *f = PFont(font_.GetID()); if (f) painter->setFont(*f); painter->setPen(convertQColor(fore)); painter->drawText(rc.left, ybase, qs); }
void ContestResultsApi::updateResults(capnp::List<ContestResults::TalliedOpinion>::Reader talliedOpinions) { // Allocate space in m_contestantResults m_contestantResults.clear(); for (auto tally : talliedOpinions) while (tally.getContestant().isContestant() && m_contestantResults.size() <= tally.getContestant().getContestant()) m_contestantResults.append(0); for (auto contestantTally : talliedOpinions) { auto tally = QVariant(static_cast<qreal>(contestantTally.getTally())); if (contestantTally.getContestant().isContestant()) m_contestantResults[contestantTally.getContestant().getContestant()] = tally; else m_writeInResults.insert(convertText(contestantTally.getContestant().getWriteIn()), tally); } emit resultsChanged(); }
void TopicEdit::setTopicText(QString s) { m_topicText=s; setText(convertText(s)); QToolTip::add(this, "<b></b>"+text()); }
XYPOSITION SurfaceImpl::WidthText(Font &font_, const char *s, int len) { return metrics(font_).width(convertText(s, len)); }
bool CSoundManager::LoadSong(char *Filename, int Nr) { if (false == InitSuccessfull) return false; bool fromrar; char *pData; char Temp[256]; unsigned long Size; char Buffer[100]; fromrar = false; // Zuerst checken, ob sich der Song in einem MOD-Ordner befindet if (CommandLineParams.RunOwnLevelList == true) { sprintf_s(Temp, "levels/%s/%s", CommandLineParams.OwnLevelList, Filename); if (FileExists(Temp)) goto loadfile; } // Dann checken, ob sich das File im Standard Ordner befindet sprintf_s(Temp, "data/%s", Filename); if (FileExists(Temp)) goto loadfile; // Auch nicht? Dann ist es hoffentlich im RAR file if (urarlib_get(&pData, &Size, Filename, RARFILENAME, convertText(RARFILEPASSWORD)) == false) { sprintf_s(Temp, "\n-> Error loading %s from Archive !\n", Filename); Protokoll.WriteText(Temp, true); return false; } else fromrar = true; loadfile: int Nummer = Nr; if (its_Songs[Nummer] != NULL) { delete(its_Songs[Nummer]); its_Songs[Nummer] = NULL; } its_Songs[Nummer] = new CSong(); if (fromrar == false) its_Songs[Nummer]->SongData = FMUSIC_LoadSong(Temp); else { its_Songs[Nummer]->SongData = FMUSIC_LoadSongEx(pData, 0, Size, FSOUND_LOADMEMORY, NULL, 0); free(pData); } // Fehler beim Laden ? // if (its_Songs[Nummer]->SongData == NULL) { strcpy_s(Buffer, strlen("\n-> Error loading ") + 1, "\n-> Error loading "); strcat_s(Buffer, strlen(Filename) + 1, Filename); strcat_s(Buffer, 3, "\n"); Protokoll.WriteText(Buffer, true); //return (-1); return false; } its_LoadedSongs++; //its_Songs[Nummer].Name = Filename; its_Songs[Nummer]->Volume = 100; its_Songs[Nummer]->FadingVolume = 0.0f; // TODO FIX /* strcpy_s(Buffer, "Load Song : "); strcat_s(Buffer, Filename); strcat_s(Buffer, " successfull\n"); Protokoll.WriteText(Buffer, false); */ //return Nummer; return true; } // LoadSong
bool DirectGraphicsSprite::LoadImage(char *Filename, int xs, int ys, int xfs, int yfs, int xfc, int yfc) { if(GameRunning == false) return false; bool fromrar; HRESULT hresult; char *pData; char Temp[256]; unsigned long Size; // zuerst eine evtl benutzte Textur freigeben SafeRelease(itsTexture); fromrar = false; // Zuerst checken, ob sich die Grafik in einem MOD-Ordner befindet if (CommandLineParams.RunOwnLevelList == true) { sprintf_s(Temp, "levels/%s/%s", CommandLineParams.OwnLevelList, Filename); if (FileExists(Temp)) goto loadfile; } // Dann checken, ob sich das File im Standard Ordner befindet sprintf_s(Temp, "data/%s", Filename); if (FileExists(Temp)) goto loadfile; // Auch nicht? Dann ist es hoffentlich im RAR file if (urarlib_get(&pData, &Size, Filename, RARFILENAME, convertText(RARFILEPASSWORD)) == false) { sprintf_s(Temp, "\n-> Error loading %s from Archive !\n", Filename); Protokoll.WriteText(Temp, true); return false; } else fromrar = true; loadfile: // normal von Platte laden? if (fromrar == false) { // Textur laden hresult = D3DXCreateTextureFromFileEx( lpD3DDevice, Temp, NULL, NULL, // x und y Grösse des Sprites (aus Datei übernehmen) 1, // Nur eine Version der Textur 0, // Immer 0 setzen D3DFMT_UNKNOWN, // Format aus der Datei lesen D3DPOOL_MANAGED, // DX bestimmt wo die Textur gespeichert wird D3DX_FILTER_NONE, // Keine Filter verwenden D3DX_FILTER_NONE, 0xFFFF00FF, // Colorkeyfarbe (Lila) NULL, // Keine Image Info NULL, // Keine Palette angeben &itsTexture); } else { // Textur aus Speicher erzeugen hresult = D3DXCreateTextureFromFileInMemoryEx( lpD3DDevice, (LPVOID)pData, Size, NULL, NULL, // x und y Grösse des Sprites (aus Datei übernehmen) 1, // Nur eine Version der Textur 0, // Immer 0 setzen D3DFMT_UNKNOWN, // Format aus der Datei lesen D3DPOOL_MANAGED, // DX bestimmt wo die Textur gespeichert wird D3DX_FILTER_NONE, // Keine Filter verwenden D3DX_FILTER_NONE, 0xFFFF00FF, // Colorkeyfarbe (Lila) NULL, // Keine Image Info NULL, // Keine Palette angeben &itsTexture); free(pData); } // Fehler beim Laden ? if(hresult != D3D_OK) { strcpy_s(Temp, strlen("Fehler beim Laden von ") + 1, "Fehler beim Laden von "); strcat_s(Temp, strlen(Filename) + 1, Filename); strcat_s(Temp, 4, " !\n"); Protokoll.WriteText(Temp, true); return false; } // Grösse der Textur anpassen D3DSURFACE_DESC desc; itsTexture->GetLevelDesc(0,&desc); // Grösse setzen itsXSize = (float)desc.Width; itsYSize = (float)desc.Height; itsXFrameCount = xfc; itsYFrameCount = yfc; itsXFrameSize = xfs; itsYFrameSize = yfs; itsRect.left = 0; itsRect.top = 0; itsRect.right = (int)itsXSize; itsRect.bottom = (int)itsYSize; // Ausschnitte vorberechnen for (int i = 0; i < xfc * yfc; i++) { itsPreCalcedRects[i].top = (i/itsXFrameCount) * itsYFrameSize; itsPreCalcedRects[i].left = (i%itsXFrameCount) * itsXFrameSize; itsPreCalcedRects[i].right = itsPreCalcedRects[i].left + itsXFrameSize; itsPreCalcedRects[i].bottom = itsPreCalcedRects[i].top + itsYFrameSize; } itsRect = itsPreCalcedRects[0]; // Bild korrekt geladen sprintf_s(Temp, "%s %s %s %s", TextArray [TEXT_LADE_BITMAP], Filename, TextArray [TEXT_LADEN_ERFOLGREICH], "\n"); Protokoll.WriteText(Temp, false); DisplayLoadInfo(Temp); LoadedTextures++; // Anzahl der geladenen Texturen erhöhen //_itoa_s(LoadedTextures, Temp, 10); // Protokoll.WriteText(Temp, false); // Protokoll.WriteText(" Sprite Textur(en) geladen !\n", false); return true; }
bool DirectGraphicsFont::LoadFont(const char *Filename, int xts, int yts, int xCharsize, int yCharsize, int xChars,int yChars) { mTexture = new (DirectGraphicsSprite); if (!mTexture->LoadImage(Filename, xts, yts, xCharsize, yCharsize, xChars, 0)) return false; // Grösse setzen // mXCharSize = xCharsize; mYCharSize = yCharsize; mXChars = xChars; mXTextureSize = xts; mYTextureSize = yts; // Länge der einzelnen Zeichen aus der Grafik bestimmen // // Geladene Font Textur locken // #if defined(PLATFORM_DIRECTX) D3DSURFACE_DESC d3dsd; D3DLOCKED_RECT d3dlr; HRESULT hresult; mTexture->itsTexture->GetLevelDesc(0, &d3dsd); hresult = mTexture->itsTexture->LockRect (0, &d3dlr, 0, 0 ); // Fehler beim Locken ? if (hresult != D3D_OK) Protokoll.WriteText("error locking font texture!", true); // Colorkey feststellen DWORD key = ((DWORD*)d3dlr.pBits)[0]; #elif defined(PLATFORM_SDL) image_t image; char Temp[256]; char *pData; unsigned long Size; if (CommandLineParams.RunOwnLevelList == true) { sprintf_s(Temp, "levels/%s/%s", CommandLineParams.OwnLevelList, Filename); if (FileExists(Temp)) { loadImage(image, Temp); } } if (image.data == NULL) { sprintf_s(Temp, "data/%s", Filename); if (FileExists(Temp)) { loadImage(image, Temp); } } if (image.data == NULL) { if (urarlib_get(&pData, &Size, Filename, RARFILENAME, convertText(RARFILEPASSWORD)) != false) { loadImage(image, pData, Size); free(pData); } } if (image.data == NULL) { return true; } #if 1 /* menufont.png: pixel at (0,0) (upper left corner) is part of a char/glyph, so pick key from lower left corner. Maybe in DirectX image is flipped vertically? */ DWORD key = (((DWORD*)image.data )[image.w * (image.h - 1)]); #else DWORD key = ((DWORD*)image.data )[0]; #endif /* // PICKLE Not OpenGLES compat, left for info int textureWidth, textureHeight; glBindTexture( GL_TEXTURE_2D, mTexture->itsTexture ); glGetTexLevelParameteriv( GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &textureWidth ); glGetTexLevelParameteriv( GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &textureHeight ); GLubyte *buffer = (GLubyte *)malloc(textureWidth*textureHeight*4); glGetTexImage( GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, buffer ); DWORD key = ((DWORD*)buffer)[0]; glBindTexture( GL_TEXTURE_2D, 0 ); */ #endif //key = 0; // Einzelne Zeichen durchgehen for (int i=0; i < xChars; i++) for (int j=0; j < yChars; j++) { int last = 0; bool found = false; for (int k = 0; k<xCharsize; k++) { found = false; for (int l = 0; l<yCharsize; l++) { #if defined(PLATFORM_DIRECTX) if (((DWORD*)d3dlr.pBits)[(j * yCharsize + l) * d3dsd.Width + (i*xCharsize + k)] != key) found = true; #elif defined(PLATFORM_SDL) if (((DWORD*)image.data)[(j * yCharsize + l) * image.w + (i*xCharsize + k)] != key) found = true; /* if (((DWORD*)buffer)[(j * yCharsize + l) * textureWidth + (i*xCharsize + k)] != key) found = true; */ #endif } if (found == true) last = k; } mCharLength[j * xChars + i] = last+1; } #if defined(PLATFORM_DIRECTX) // Unlocken mTexture->itsTexture->UnlockRect(0); #elif defined(PLATFORM_SDL) delete [] image.data; #endif return false; }
bool CSoundManager::LoadWave(char *Filename, int Nr, bool looped) { if (false == InitSuccessfull) return false; if(GameRunning == false) return false; bool fromrar; char *pData; char Temp[256]; unsigned long Size; char Buffer[100]; fromrar = false; int Nummer = Nr; if (its_Sounds[Nummer] != NULL) { delete(its_Sounds[Nummer]); its_Sounds[Nummer] = NULL; } // Zuerst checken, ob sich der Sound in einem MOD-Ordner befindet if (CommandLineParams.RunOwnLevelList == true) { sprintf_s(Temp, "levels/%s/%s", CommandLineParams.OwnLevelList, Filename); if (FileExists(Temp)) goto loadfile; } // Dann checken, ob sich das File im Standard Ordner befindet sprintf_s(Temp, "data/%s", Filename); if (FileExists(Temp)) goto loadfile; // Auch nicht? Dann ist es hoffentlich im RAR file if (urarlib_get(&pData, &Size, Filename, RARFILENAME, convertText(RARFILEPASSWORD)) == false) { sprintf_s(Temp, "\n-> Error loading %s from Archive !\n", Filename); Protokoll.WriteText(Temp, true); return false; } else fromrar = true; loadfile: its_Sounds[Nummer] = new CWave(); // von Platte laden if (fromrar == false) { if (looped == false) its_Sounds[Nummer]->SoundData = FSOUND_Sample_Load(Nr, Temp, FSOUND_LOOP_OFF, 0, Size); else // mit Loop laden its_Sounds[Nummer]->SoundData = FSOUND_Sample_Load(Nr, Temp, FSOUND_LOOP_NORMAL, 0, Size); } // aus Rarfile laden else { if (looped == false) its_Sounds[Nummer]->SoundData = FSOUND_Sample_Load(Nr, pData, FSOUND_LOADMEMORY | FSOUND_LOOP_OFF, 0, Size); else // mit Loop laden its_Sounds[Nummer]->SoundData = FSOUND_Sample_Load(Nr, pData, FSOUND_LOADMEMORY | FSOUND_LOOP_NORMAL, 0, Size); free(pData); } // Temp Datei wieder löschen und Speicher freigeben //DeleteFile("temp.dat"); //free(pData); // Und bei bedarf den loop ausschalten //if (looped == false) // FSOUND_Sample_SetLoopMode(its_Sounds[Nummer]->SoundData, FSOUND_LOOP_OFF); // Fehler beim Laden ? // if (its_Sounds[Nummer]->SoundData == NULL) { // TODO FIX /* strcpy_s(Buffer, "\n-> Error loading "); strcat_s(Buffer, Filename); strcat_s(Buffer, "\n"); Protokoll.WriteText(Buffer, true); */ // return (-1); return false; } its_Sounds[Nummer]->isLooped = looped; its_LoadedSounds++; //its_Sounds[Nummer].Name = Filename; // kurz anspielen und wieder stoppen int Channel = FSOUND_PlaySound (FSOUND_FREE, its_Sounds[Nr]->SoundData); FSOUND_SetVolume(Channel, 0); FSOUND_StopSound(Channel); // TODO FIX /* strcpy_s(Buffer, TextArray [TEXT_LADE_WAVE]); strcat_s(Buffer, Filename); strcat_s(Buffer, TextArray [TEXT_LADEN_ERFOLGREICH]); strcat_s(Buffer, " \n"); Protokoll.WriteText(Buffer, false);*/ DisplayLoadInfo(Buffer); //return Nummer; return true; } // LoadWave
void TopicEdit::focusOutEvent ( QFocusEvent * ) { setText(convertText(m_topicText)); }
void Converter::convertSingleExcel(const std::string& fileName) { tWorkbooksSp wbs = excel()->getWorkbooks(); tWorkbookSp wb = wbs->open(toUtf16(getInputAbsPath(fileName))); if (!wb) { logError(logger(), "Error while opening excel file: " + fileName); return; } tWorksheetsSp wss = wb->worksheets(); int numSheets = wss->getCount(); for (int i = 1; i <= numSheets; ++i) { tWorksheetSp ws = wss->getItem(i); if (!ws) { std::cout << "no worksheet at index: " << i << std::endl; } std::cout << "Processing worksheet " << i << " / " << numSheets << std::endl; if (excelVisible_) ws->activate(); tExcelRangeSp r = ws->usedRange(); //r = r->cells(); int rows = r->numRows(); int cols = r->numCols(); int count = r->count(); std::wstring wstr; std::wstring wstrUni; int total = rows * cols; int current = 0, lastDisplayed = 0; for (int j = 1; j <= count; ++j) { tExcelRangeSp cc = r->item(j); convertText(cc, wstr, wstrUni); current = (int)(100.0 * (double)(j) / (double)total); if (lastDisplayed < current) { lastDisplayed = current; std::cout << lastDisplayed << " % completed\r"; } } // while (count > 0) { // std::cout << er->getIDispatch() << std::endl; // wstr = er->getText(); // tFontSp font = er->getFont(); // std::cout << font->getName() << std::endl; // convertText(font, wstr, wstrUni); // // //std::wcout << wstr << std::endl; // er = er->next(); // --count; // } } string_t outputDir = getOutputAbsPath(fileName); Poco::File(outputDir).createDirectories(); Poco::Path p(fileName); logInfo(logger(), "Saving worksheet..."); std::string newName = outputDir + p.getBaseName() + " UNICODE." + p.getExtension(); Poco::File pf(newName); if (pf.exists()) pf.remove(); wb->saveAs(newName); wb->close(); logInfo(logger(), "Save was successful."); }
QString KicadSchematic2Svg::convert(const QString & filename, const QString & defName) { initLimits(); QFile file(filename); if (!file.open(QFile::ReadOnly)) { throw QObject::tr("unable to open %1").arg(filename); } QTextStream textStream(&file); QString metadata = makeMetadata(filename, "schematic part", defName); metadata += endMetadata(); QString reference; int textOffset = 0; bool drawPinNumber = true; bool drawPinName = true; bool gotDef = false; while (true) { QString line = textStream.readLine(); if (line.isNull()) { break; } if (line.startsWith("DEF") && line.contains(defName, Qt::CaseInsensitive)) { QStringList defs = splitLine(line); if (defs.count() < 8) { throw QObject::tr("bad schematic definition %1").arg(filename); } reference = defs[2]; textOffset = defs[4].toInt(); drawPinName = defs[6] == "Y"; drawPinNumber = defs[5] == "Y"; gotDef = true; break; } } if (!gotDef) { throw QObject::tr("schematic part %1 not found in %2").arg(defName).arg(filename); } QString contents = "<g id='schematic'>\n"; bool inFPLIST = false; while (true) { QString fline = textStream.readLine(); if (fline.isNull()) { throw QObject::tr("schematic %1 unexpectedly ends (1) in %2").arg(defName).arg(filename); } if (fline.contains("ENDDEF")) { throw QObject::tr("schematic %1 unexpectedly ends (2) in %2").arg(defName).arg(filename); } if (fline.startsWith("DRAW")) { break; } if (fline.startsWith("ALIAS")) continue; if (fline.startsWith("F")) { contents += convertField(fline); continue; } if (fline.startsWith("$FPLIST")) { inFPLIST = true; break; } } while (inFPLIST) { QString fline = textStream.readLine(); if (fline.isNull()) { throw QObject::tr("schematic %1 unexpectedly ends (1) in %2").arg(defName).arg(filename); } if (fline.startsWith("$ENDFPLIST")) { inFPLIST = false; break; } if (fline.contains("ENDDEF")) { throw QObject::tr("schematic %1 unexpectedly ends (2) in %2").arg(defName).arg(filename); } } int pinIndex = 0; while (true) { QString line = textStream.readLine(); if (line.isNull()) { throw QObject::tr("schematic %1 unexpectedly ends (3) in %2").arg(defName).arg(filename); } if (line.startsWith("DRAW")) { continue; } if (line.contains("ENDDEF")) { break; } if (line.contains("ENDDRAW")) { break; } if (line.startsWith("S")) { contents += convertRect(line); } else if (line.startsWith("X")) { // need to look at them all before formatting (I think) contents += convertPin(line, textOffset, drawPinName, drawPinNumber, pinIndex++); } else if (line.startsWith("C")) { contents += convertCircle(line); } else if (line.startsWith("P")) { contents += convertPoly(line); } else if (line.startsWith("A")) { contents += convertArc(line); } else if (line.startsWith("T")) { contents += convertText(line); } else { DebugDialog::debug("Unknown line " + line); } } contents += "</g>\n"; QString svg = TextUtils::makeSVGHeader(GraphicsUtils::StandardFritzingDPI, GraphicsUtils::StandardFritzingDPI, m_maxX - m_minX, m_maxY - m_minY) + m_title + m_description + metadata + offsetMin(contents) + "</svg>"; return svg; }
// // Got a lot of good ideas from pykaraoke by Kelvin Lawson ([email protected]). Thanks! // void CKaraokeLyricsTextKAR::parseMIDI() { m_midiOffset = 0; // Bytes 0-4: header unsigned int header = readDword(); // If we get MS RIFF header, skip it if ( header == 0x52494646 ) { setPos( currentPos() + 16 ); header = readDword(); } // MIDI header if ( header != 0x4D546864 ) throw( "Not a MIDI file" ); // Bytes 5-8: header length unsigned int header_length = readDword(); // Bytes 9-10: format unsigned short format = readWord(); if ( format > 2 ) throw( "Unsupported format" ); // Bytes 11-12: tracks unsigned short tracks = readWord(); // Bytes 13-14: divisious unsigned short divisions = readWord(); if ( divisions > 32768 ) throw( "Unsupported division" ); // Number of tracks is always 1 if format is 0 if ( format == 0 ) tracks = 1; // Parsed per-channel info std::vector<MidiLyrics> lyrics; std::vector<MidiTempo> tempos; std::vector<MidiChannelInfo> channels; channels.resize( tracks ); // Set up default tempo MidiTempo te; te.clocks = 0; te.tempo = 500000; tempos.push_back( te ); int preferred_lyrics_track = -1; int lastchannel = 0; int laststatus = 0; unsigned int firstNoteClocks = 1000000000; // arbitrary large value unsigned int next_line_flag = 0; // Point to first byte after MIDI header setPos( 8 + header_length ); // Parse all tracks for ( int track = 0; track < tracks; track++ ) { char tempbuf[1024]; unsigned int clocks = 0; channels[track].total_lyrics = 0; channels[track].total_lyrics_space = 0; // Skip malformed files if ( readDword() != 0x4D54726B ) throw( "Malformed track header" ); // Next track position int tracklen = readDword(); unsigned int nexttrackstart = tracklen + currentPos(); // Parse track until end of track event while ( currentPos() < nexttrackstart ) { // field length clocks += readVarLen(); unsigned char msgtype = readByte(); // // Meta event // if ( msgtype == 0xFF ) { unsigned char metatype = readByte(); unsigned int metalength = readVarLen(); if ( metatype == 3 ) { // Track title metatype if ( metalength >= sizeof( tempbuf ) ) throw( "Meta event too long" ); readData( tempbuf, metalength ); tempbuf[metalength] = '\0'; if ( !strcmp( tempbuf, "Words" ) ) preferred_lyrics_track = track; } else if ( metatype == 5 || metatype == 1 ) { // Lyrics metatype if ( metalength >= sizeof( tempbuf ) ) throw( "Meta event too long" ); readData( tempbuf, metalength ); tempbuf[metalength] = '\0'; if ( (tempbuf[0] == '@' && tempbuf[1] >= 'A' && tempbuf[1] <= 'Z') || strstr( tempbuf, " SYX" ) || strstr( tempbuf, "Track-" ) || strstr( tempbuf, "%-" ) || strstr( tempbuf, "%+" ) ) { // Keywords if ( tempbuf[0] == '@' && tempbuf[1] == 'T' && strlen( tempbuf + 2 ) > 0 ) { if ( m_songName.empty() ) m_songName = convertText( tempbuf + 2 ); else { if ( !m_artist.empty() ) m_artist += "[CR]"; m_artist += convertText( tempbuf + 2 ); } } } else { MidiLyrics lyric; lyric.clocks = clocks; lyric.track = track; lyric.flags = next_line_flag; if ( tempbuf[0] == '\\' ) { lyric.flags = CKaraokeLyricsText::LYRICS_NEW_PARAGRAPH; lyric.text = convertText( tempbuf + 1 ); } else if ( tempbuf[0] == '/' ) { lyric.flags = CKaraokeLyricsText::LYRICS_NEW_LINE; lyric.text = convertText( tempbuf + 1 ); } else if ( tempbuf[1] == '\0' && (tempbuf[0] == '\n' || tempbuf[0] == '\r' ) ) { // An empty line; do not add it but set the flag if ( next_line_flag == CKaraokeLyricsText::LYRICS_NEW_LINE ) next_line_flag = CKaraokeLyricsText::LYRICS_NEW_PARAGRAPH; else next_line_flag = CKaraokeLyricsText::LYRICS_NEW_LINE; } else { next_line_flag = (strchr(tempbuf, '\n') || strchr(tempbuf, '\r')) ? CKaraokeLyricsText::LYRICS_NEW_LINE : CKaraokeLyricsText::LYRICS_NONE; lyric.text = convertText( tempbuf ); } lyrics.push_back( lyric ); // Calculate the number of spaces in current syllable for ( unsigned int j = 0; j < metalength; j++ ) { channels[ track ].total_lyrics++; if ( tempbuf[j] == 0x20 ) channels[ track ].total_lyrics_space++; } } } else if ( metatype == 0x51 ) { // Set tempo event if ( metalength != 3 ) throw( "Invalid tempo" ); unsigned char a1 = readByte(); unsigned char a2 = readByte(); unsigned char a3 = readByte(); unsigned int tempo = (a1 << 16) | (a2 << 8) | a3; // MIDI spec says tempo could only be on the first track... // but some MIDI editors still put it on second. Shouldn't break anything anyway, but let's see //if ( track != 0 ) // throw( "Invalid tempo track" ); // Check tempo array. If previous tempo has higher clocks, abort. if ( tempos.size() > 0 && tempos[ tempos.size() - 1 ].clocks > clocks ) throw( "Invalid tempo" ); // If previous tempo has the same clocks value, override it. Otherwise add new. if ( tempos.size() > 0 && tempos[ tempos.size() - 1 ].clocks == clocks ) tempos[ tempos.size() - 1 ].tempo = tempo; else { MidiTempo mt; mt.clocks = clocks; mt.tempo = tempo; tempos.push_back( mt ); } } else { // Skip the event completely setPos( currentPos() + metalength ); } } else if ( msgtype== 0xF0 || msgtype == 0xF7 ) { // SysEx event unsigned int length = readVarLen(); setPos( currentPos() + length ); } else { // Regular MIDI event if ( msgtype & 0x80 ) { // Status byte laststatus = ( msgtype >> 4) & 0x07; lastchannel = msgtype & 0x0F; if ( laststatus != 0x07 ) msgtype = readByte() & 0x7F; } switch ( laststatus ) { case 0: // Note off readByte(); break; case 1: // Note on if ( (readByte() & 0x7F) != 0 ) // this would be in fact Note off { // Remember the time the first note played if ( firstNoteClocks > clocks ) firstNoteClocks = clocks; } break; case 2: // Key Pressure case 3: // Control change case 6: // Pitch wheel readByte(); break; case 4: // Program change case 5: // Channel pressure break; default: // case 7: Ignore this event if ( (lastchannel & 0x0F) == 2 ) // Sys Com Song Position Pntr readWord(); else if ( (lastchannel & 0x0F) == 3 ) // Sys Com Song Select(Song #) readByte(); break; } } } }