void TagReader::SetUnsyncLyricsFrame(const std::string& value, TagLib::ID3v2::Tag* tag) const { TagLib::ByteVector id_vector("USLT"); QVector<TagLib::ByteVector> frames_buffer; // Store and clear existing frames while (tag->frameListMap().contains(id_vector) && tag->frameListMap()[id_vector].size() != 0) { frames_buffer.push_back(tag->frameListMap()[id_vector].front()->render()); tag->removeFrame(tag->frameListMap()[id_vector].front()); } // If no frames stored create empty frame if (frames_buffer.isEmpty()) { TagLib::ID3v2::UnsynchronizedLyricsFrame frame(TagLib::String::UTF8); frame.setDescription("Clementine editor"); frames_buffer.push_back(frame.render()); } // Update and add the frames for (int lyrics_index = 0; lyrics_index < frames_buffer.size(); lyrics_index++) { TagLib::ID3v2::UnsynchronizedLyricsFrame* frame = new TagLib::ID3v2::UnsynchronizedLyricsFrame( frames_buffer.at(lyrics_index)); if (lyrics_index == 0) { frame->setText(StdStringToTaglibString(value)); } // add frame takes ownership and clears the memory tag->addFrame(frame); } }
void TagReader::SetTextFrame(const char* id, const std::string& value, TagLib::ID3v2::Tag* tag) const { TagLib::ByteVector id_vector(id); // Remove the frame if it already exists while (tag->frameListMap().contains(id_vector) && tag->frameListMap()[id_vector].size() != 0) { tag->removeFrame(tag->frameListMap()[id_vector].front()); } // Create and add a new frame TagLib::ID3v2::TextIdentificationFrame* frame = new TagLib::ID3v2::TextIdentificationFrame(id_vector, TagLib::String::UTF8); frame->setText(StdStringToTaglibString(value)); tag->addFrame(frame); }
extern int shapeop_addUniformLaplacianConstraint(ShapeOpSolver *op, int *ids, int nb_ids, int displacement_lap, ShapeOpScalar weight) { std::vector<int> id_vector(ids, ids + nb_ids); auto c = std::make_shared<ShapeOp::UniformLaplacianConstraint>(id_vector, weight, op->s->getPoints(), displacement_lap != 0); return op->s->addConstraint(c); }
extern int shapeop_addLineConstraint(ShapeOpSolver *op, int *ids, int nb_ids, ShapeOpScalar weight) { std::vector<int> id_vector(ids, ids + nb_ids); auto c = std::make_shared<ShapeOp::LineConstraint>(id_vector, weight, op->s->getPoints()); return op->s->addConstraint(c); }
// Write a new BWT and SAI that skips the elements marked // by the gap array. This is used to remove entire strings from the // index void writeRemovalIndex(const BWT* pBWTInternal, const std::string& sai_inname, const std::string& bwt_outname, const std::string& sai_outname, size_t num_strings_remove, size_t num_symbols_remove, const GapArray* pGapArray) { IBWTWriter* pBWTWriter = BWTWriter::createWriter(bwt_outname); SAWriter* pSAIWriter = new SAWriter(sai_outname); SAReader* pSAIReader = new SAReader(sai_inname); // Calculate and write header values assert(num_strings_remove < pBWTInternal->getNumStrings()); assert(num_symbols_remove < pBWTInternal->getBWLen()); size_t input_strings = pBWTInternal->getNumStrings(); size_t input_symbols = pBWTInternal->getBWLen(); size_t output_strings = input_strings - num_strings_remove; size_t output_symbols = input_symbols - num_symbols_remove; pBWTWriter->writeHeader(output_strings, output_symbols, BWF_NOFMI); // Discard the header of the sai size_t discard1, discard2; pSAIReader->readHeader(discard1, discard2); // Write the header of the SAI which is just the number of strings and elements in the SAI pSAIWriter->writeHeader(output_strings, output_strings); // We need to fix the IDs in the SAI. We do this by tracking // the number of IDs that are removed that are lower than a given // id. std::vector<int> id_vector(pBWTInternal->getNumStrings(), 0); // Calculate and write the actual string // The gap array marks the symbols that should be removed. We // iterate over the gap array, if the value is zero, we output // the BWT symbol. Otherwise we skip the number of elements // indicated by the gap. size_t num_bwt_wrote = 0; size_t num_sai_wrote = 0; size_t i = 0; while(i < input_symbols) { size_t v = pGapArray->get(i); // If v is zero we output a single symbol, otherwise // we skip v elements. size_t num_to_read = (v == 0) ? 1 : v; for(size_t j = 0; j < num_to_read; ++j) { char b = pBWTInternal->getChar(i); if(b == '$') { SAElem e = pSAIReader->readElem(); // This element of the SAI will be removed, // increment the id vector so we can correct // the indices later if(v > 0) { id_vector[e.getID()]++; } } // output if(v == 0) { pBWTWriter->writeBWChar(b); assert(b != '\n'); ++num_bwt_wrote; } } i += num_to_read; } if(num_bwt_wrote != output_symbols) { printf("Error expected to write %zu symbols, actually wrote %zu\n", output_symbols, num_bwt_wrote); assert(num_bwt_wrote == output_symbols); } // Finalize the BWT disk file pBWTWriter->finalize(); // Accumulate the counts for each id int prev = 0; for(size_t i = 0; i < id_vector.size(); ++i) { id_vector[i] += prev; prev = id_vector[i]; } // Read the SAI file again, writing out the // corrected IDs that are not marked for removal delete pSAIReader; pSAIReader = new SAReader(sai_inname); pSAIReader->readHeader(discard1, discard2); for(size_t i = 0; i < input_strings; ++i) { SAElem e = pSAIReader->readElem(); uint64_t id = e.getID(); int prev_count = (id > 0) ? id_vector[id - 1] : 0; int count = id_vector[id]; if(count == prev_count) { // the current element should be output, it wasn't marked for removal id -= count; e.setID(id); pSAIWriter->writeElem(e); ++num_sai_wrote; } } assert(num_sai_wrote == output_strings); delete pSAIReader; delete pSAIWriter; delete pBWTWriter; }