/[svn]/gigedit/trunk/src/gigedit/CombineInstrumentsDialog.cpp
ViewVC logotype

Diff of /gigedit/trunk/src/gigedit/CombineInstrumentsDialog.cpp

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 2548 by schoenebeck, Tue May 13 12:17:43 2014 UTC revision 2550 by schoenebeck, Wed May 14 01:31:30 2014 UTC
# Line 251  inline int getDimensionIndex(gig::dimens Line 251  inline int getDimensionIndex(gig::dimens
251  }  }
252    
253  static void fillDimValues(uint* values/*[8]*/, DimensionCase dimCase, gig::Region* rgn, bool bShouldHaveAllDimensionsPassed) {  static void fillDimValues(uint* values/*[8]*/, DimensionCase dimCase, gig::Region* rgn, bool bShouldHaveAllDimensionsPassed) {
254        #if DEBUG_COMBINE_INSTRUMENTS
255        printf("dimvalues = { ");
256        fflush(stdout);
257        #endif
258      for (DimensionCase::iterator it = dimCase.begin(); it != dimCase.end(); ++it) {      for (DimensionCase::iterator it = dimCase.begin(); it != dimCase.end(); ++it) {
259          gig::dimension_t type = it->first;          gig::dimension_t type = it->first;
260          int iDimIndex = getDimensionIndex(type, rgn);          int iDimIndex = getDimensionIndex(type, rgn);
261          if (bShouldHaveAllDimensionsPassed) assert(iDimIndex >= 0);          if (bShouldHaveAllDimensionsPassed) assert(iDimIndex >= 0);
262          else if (iDimIndex < 0) continue;          else if (iDimIndex < 0) continue;
263          values[iDimIndex] = it->second;          values[iDimIndex] = it->second;
264            #if DEBUG_COMBINE_INSTRUMENTS
265            printf("%x=%d, ", type, it->second);
266            #endif
267      }      }
268        #if DEBUG_COMBINE_INSTRUMENTS
269        printf("\n");
270        #endif
271  }  }
272    
273  static DimensionRegionUpperLimits getDimensionRegionUpperLimits(gig::DimensionRegion* dimRgn) {  static DimensionRegionUpperLimits getDimensionRegionUpperLimits(gig::DimensionRegion* dimRgn) {
274      DimensionRegionUpperLimits limits;      DimensionRegionUpperLimits limits;
275      gig::Region* rgn = dimRgn->GetParent();      gig::Region* rgn = dimRgn->GetParent();
276      for (int d = 0; d < rgn->Dimensions; ++d) {      for (uint d = 0; d < rgn->Dimensions; ++d) {
277          const gig::dimension_def_t& def = rgn->pDimensionDefinitions[d];          const gig::dimension_def_t& def = rgn->pDimensionDefinitions[d];
278          limits[def.dimension] = dimRgn->DimensionUpperLimits[d];          limits[def.dimension] = dimRgn->DimensionUpperLimits[d];
279      }      }
# Line 291  static void restoreDimensionRegionUpperL Line 301  static void restoreDimensionRegionUpperL
301   */   */
302  inline int baseBits(gig::dimension_t type, gig::Region* rgn) {  inline int baseBits(gig::dimension_t type, gig::Region* rgn) {
303      int previousBits = 0;      int previousBits = 0;
304      for (int i = 0; i < rgn->Dimensions; ++i) {      for (uint i = 0; i < rgn->Dimensions; ++i) {
305          if (rgn->pDimensionDefinitions[i].dimension == type) break;          if (rgn->pDimensionDefinitions[i].dimension == type) break;
306          previousBits += rgn->pDimensionDefinitions[i].bits;          previousBits += rgn->pDimensionDefinitions[i].bits;
307      }      }
# Line 332  static DimensionZones preciseDimensionZo Line 342  static DimensionZones preciseDimensionZo
342      int iBaseBits = baseBits(type, rgn);      int iBaseBits = baseBits(type, rgn);
343      int mask = ~(((1 << def.bits) - 1) << iBaseBits);      int mask = ~(((1 << def.bits) - 1) << iBaseBits);
344    
345        #if DEBUG_COMBINE_INSTRUMENTS
346        printf("velo zones { ");
347        fflush(stdout);
348        #endif
349      int iLow = 0;      int iLow = 0;
350      for (int z = 0; z < def.zones; ++z) {      for (int z = 0; z < def.zones; ++z) {
351          gig::DimensionRegion* dimRgn2 =          gig::DimensionRegion* dimRgn2 =
352              rgn->pDimensionRegions[ (iDimRgn & mask) | ( z << iBaseBits) ];              rgn->pDimensionRegions[ (iDimRgn & mask) | ( z << iBaseBits) ];
353          int iHigh = dimRgn2->DimensionUpperLimits[iDimension];          int iHigh = dimRgn2->DimensionUpperLimits[iDimension];
354          DLS::range_t range = { iLow, iHigh};          DLS::range_t range = { iLow, iHigh};
355            #if DEBUG_COMBINE_INSTRUMENTS
356            printf("%d..%d, ", iLow, iHigh);
357            fflush(stdout);
358            #endif
359          zones.push_back(range);          zones.push_back(range);
360          iLow = iHigh + 1;          iLow = iHigh + 1;
361      }      }
362        #if DEBUG_COMBINE_INSTRUMENTS
363        printf("}\n");
364        #endif
365      return zones;      return zones;
366  }  }
367    
368    struct CopyAssignSchedEntry {
369        gig::DimensionRegion* src;
370        gig::DimensionRegion* dst;
371        int velocityZone;
372        int totalSrcVelocityZones;
373    };
374    typedef std::vector<CopyAssignSchedEntry> CopyAssignSchedule;
375    
376  /** @brief Copy all DimensionRegions from source Region to target Region.  /** @brief Copy all DimensionRegions from source Region to target Region.
377   *   *
378   * Copies the entire articulation informations (including sample reference of   * Copies the entire articulation informations (including sample reference of
# Line 359  static DimensionZones preciseDimensionZo Line 388  static DimensionZones preciseDimensionZo
388   *   *
389   * @param outRgn - where the dimension regions shall be copied to   * @param outRgn - where the dimension regions shall be copied to
390   * @param inRgn - all dimension regions that shall be copied from   * @param inRgn - all dimension regions that shall be copied from
391   * @param dims - dimension definitions of target region   * @param dims - precise dimension definitions of target region
392   * @param iDstLayer - layer number of destination region where the dimension   * @param iDstLayer - layer index of destination region where the dimension
393   *                    regions shall be copied to   *                    regions shall be copied to
394   * @param iSrcLayer - layer number of the source region where the dimension   * @param iSrcLayer - layer index of the source region where the dimension
395   *                    regions shall be copied from   *                    regions shall be copied from
396   * @param dimCase - just for internal purpose (function recursion), don't pass   * @param dimCase - just for internal purpose (function recursion), don't pass
397   *                  anything here, this function will call itself recursively   *                  anything here, this function will call itself recursively
398   *                  will fill this container with concrete dimension values for   *                  will fill this container with concrete dimension values for
399   *                  selecting the precise dimension regions during its task   *                  selecting the precise dimension regions during its task
400     * @param schedule - just for internal purpose (function recursion), don't pass
401                         anything here: list of all DimensionRegion copy operations
402     *                   which is filled during the nested loops / recursions of
403     *                   this function call, they will be peformed after all
404     *                   function recursions have been completed
405   */   */
406  static void copyDimensionRegions(gig::Region* outRgn, gig::Region* inRgn, Dimensions dims, int iDstLayer, int iSrcLayer, DimensionCase dimCase = DimensionCase()) {  static void copyDimensionRegions(gig::Region* outRgn, gig::Region* inRgn, Dimensions dims, int iDstLayer, int iSrcLayer, DimensionCase dimCase = DimensionCase(), CopyAssignSchedule* schedule = NULL) {
407      if (dims.empty()) {      const bool isHighestLevelOfRecursion = !schedule;
408    
409        if (isHighestLevelOfRecursion)
410            schedule = new CopyAssignSchedule;
411    
412        if (dims.empty()) { // reached deepest level of function recursion ...
413            CopyAssignSchedEntry e;
414    
415          // resolve the respective source & destination DimensionRegion ...                  // resolve the respective source & destination DimensionRegion ...        
416          uint srcDimValues[8] = {};          uint srcDimValues[8] = {};
417          uint dstDimValues[8] = {};          uint dstDimValues[8] = {};
# Line 379  static void copyDimensionRegions(gig::Re Line 420  static void copyDimensionRegions(gig::Re
420          srcDimCase[gig::dimension_layer] = iSrcLayer;          srcDimCase[gig::dimension_layer] = iSrcLayer;
421          dstDimCase[gig::dimension_layer] = iDstLayer;          dstDimCase[gig::dimension_layer] = iDstLayer;
422    
423            #if DEBUG_COMBINE_INSTRUMENTS
424            printf("-------------------------------\n");
425            #endif
426    
427          // first select source & target dimension region with an arbitrary          // first select source & target dimension region with an arbitrary
428          // velocity split zone, to get access to the precise individual velocity          // velocity split zone, to get access to the precise individual velocity
429          // split zone sizes (if there is actually a velocity dimension at all,          // split zone sizes (if there is actually a velocity dimension at all,
430          // otherwise we already select the desired source & target dimension          // otherwise we already select the desired source & target dimension
431          // region here)          // region here)
432            #if DEBUG_COMBINE_INSTRUMENTS
433            printf("src "); fflush(stdout);
434            #endif
435          fillDimValues(srcDimValues, srcDimCase, inRgn, false);          fillDimValues(srcDimValues, srcDimCase, inRgn, false);
436            #if DEBUG_COMBINE_INSTRUMENTS
437            printf("dst "); fflush(stdout);
438            #endif
439          fillDimValues(dstDimValues, dstDimCase, outRgn, true);          fillDimValues(dstDimValues, dstDimCase, outRgn, true);
440          gig::DimensionRegion* srcDimRgn = inRgn->GetDimensionRegionByValue(srcDimValues);          gig::DimensionRegion* srcDimRgn = inRgn->GetDimensionRegionByValue(srcDimValues);
441          gig::DimensionRegion* dstDimRgn = outRgn->GetDimensionRegionByValue(dstDimValues);          gig::DimensionRegion* dstDimRgn = outRgn->GetDimensionRegionByValue(dstDimValues);
442            #if DEBUG_COMBINE_INSTRUMENTS
443            printf("iDstLayer=%d iSrcLayer=%d\n", iDstLayer, iSrcLayer);
444            printf("srcDimRgn=%lx dstDimRgn=%lx\n", (uint64_t)srcDimRgn, (uint64_t)dstDimRgn);
445            printf("srcSample='%s' dstSample='%s'\n",
446                   (!srcDimRgn->pSample ? "NULL" : srcDimRgn->pSample->pInfo->Name.c_str()),
447                   (!dstDimRgn->pSample ? "NULL" : dstDimRgn->pSample->pInfo->Name.c_str())
448            );
449            #endif
450    
451            assert(srcDimRgn->GetParent() == inRgn);
452            assert(dstDimRgn->GetParent() == outRgn);
453    
454          // now that we have access to the precise velocity split zone upper          // now that we have access to the precise velocity split zone upper
455          // limits, we can select the actual source & destination dimension          // limits, we can select the actual source & destination dimension
456          // regions we need to copy (assuming that source or target region has          // regions we need to copy (assuming that source or target region has
457          // a velocity dimension)          // a velocity dimension)
458          if (outRgn->GetDimensionDefinition(gig::dimension_velocity)) {          if (outRgn->GetDimensionDefinition(gig::dimension_velocity)) {
459              // re-select target dimension region              // re-select target dimension region (with correct velocity zone)
460              DimensionZones zones = preciseDimensionZonesFor(gig::dimension_velocity, dstDimRgn);              DimensionZones dstZones = preciseDimensionZonesFor(gig::dimension_velocity, dstDimRgn);
461              assert(zones.size() > 1);              assert(dstZones.size() > 1);
462              const int iZoneIndex = dstDimCase[gig::dimension_velocity];              int iZoneIndex = dstDimCase[gig::dimension_velocity];
463              assert(iZoneIndex <= zones.size());              e.velocityZone = iZoneIndex;
464              dstDimCase[gig::dimension_velocity] = zones[iZoneIndex].low; // arbitrary value between low and high              #if DEBUG_COMBINE_INSTRUMENTS
465                printf("dst velocity zone: %d/%d\n", iZoneIndex, (int)dstZones.size());
466                #endif
467                assert(uint(iZoneIndex) < dstZones.size());
468                dstDimCase[gig::dimension_velocity] = dstZones[iZoneIndex].low; // arbitrary value between low and high
469                #if DEBUG_COMBINE_INSTRUMENTS
470                printf("dst velocity value = %d\n", dstDimCase[gig::dimension_velocity]);
471                printf("dst refilled "); fflush(stdout);
472                #endif
473              fillDimValues(dstDimValues, dstDimCase, outRgn, true);              fillDimValues(dstDimValues, dstDimCase, outRgn, true);
474              dstDimRgn = outRgn->GetDimensionRegionByValue(dstDimValues);              dstDimRgn = outRgn->GetDimensionRegionByValue(dstDimValues);
475                #if DEBUG_COMBINE_INSTRUMENTS
476                printf("reselected dstDimRgn=%lx\n", (uint64_t)dstDimRgn);
477                printf("dstSample='%s'\n",
478                    (!dstDimRgn->pSample ? "NULL" : dstDimRgn->pSample->pInfo->Name.c_str())
479                );
480                #endif
481    
482              // re-select source dimension region              // re-select source dimension region with correct velocity zone
483              // (if it has a velocity dimension)              // (if it has a velocity dimension that is)
484              if (inRgn->GetDimensionDefinition(gig::dimension_velocity)) {              if (inRgn->GetDimensionDefinition(gig::dimension_velocity)) {
485                  srcDimCase[gig::dimension_velocity] = zones[iZoneIndex].low; // same value as used above for target dimension region                  DimensionZones srcZones = preciseDimensionZonesFor(gig::dimension_velocity, srcDimRgn);
486                    e.totalSrcVelocityZones = srcZones.size();
487                    assert(srcZones.size() > 1);
488                    if (uint(iZoneIndex) >= srcZones.size())
489                        iZoneIndex  = srcZones.size() - 1;
490                    srcDimCase[gig::dimension_velocity] = srcZones[iZoneIndex].low; // same zone as used above for target dimension region (no matter what the precise zone ranges are)
491                    #if DEBUG_COMBINE_INSTRUMENTS
492                    printf("src refilled "); fflush(stdout);
493                    #endif
494                  fillDimValues(srcDimValues, srcDimCase, inRgn, false);                  fillDimValues(srcDimValues, srcDimCase, inRgn, false);
495                  srcDimRgn = inRgn->GetDimensionRegionByValue(srcDimValues);                  srcDimRgn = inRgn->GetDimensionRegionByValue(srcDimValues);
496                    #if DEBUG_COMBINE_INSTRUMENTS
497                    printf("reselected srcDimRgn=%lx\n", (uint64_t)srcDimRgn);
498                    printf("srcSample='%s'\n",
499                        (!srcDimRgn->pSample ? "NULL" : srcDimRgn->pSample->pInfo->Name.c_str())
500                    );
501                    #endif
502              }              }
503          }          }
504    
505          // backup the target DimensionRegion's current dimension zones upper          // Schedule copy opertion of source -> target DimensionRegion for the
506          // limits (because the target DimensionRegion's upper limits are already          // time after all nested loops have been traversed. We have to postpone
507          // defined correctly since calling AddDimension(), and the CopyAssign()          // the actual copy operations this way, because otherwise it would
508          // call next, will overwrite those upper limits unfortunately          // overwrite informations inside the destination DimensionRegion object
509          DimensionRegionUpperLimits dstUpperLimits = getDimensionRegionUpperLimits(dstDimRgn);          // that we need to read in the code block above.
510          DimensionRegionUpperLimits srcUpperLimits = getDimensionRegionUpperLimits(srcDimRgn);          e.src = srcDimRgn;
511            e.dst = dstDimRgn;
512          // copy over the selected DimensionRegion          schedule->push_back(e);
         const gig::Region* const origRgn = dstDimRgn->GetParent(); // just for sanity check below  
         dstDimRgn->CopyAssign(srcDimRgn);  
         assert(origRgn == dstDimRgn->GetParent());  
   
         // restore all original dimension zone upper limits except of the  
         // velocity dimension, because the velocity dimension zone sizes are  
         // allowed to differ for individual DimensionRegions in gig v3 format  
         if (srcUpperLimits.count(gig::dimension_velocity)) {  
             assert(dstUpperLimits.count(gig::dimension_velocity));  
             dstUpperLimits[gig::dimension_velocity] = srcUpperLimits[gig::dimension_velocity];  
         }  
         restoreDimensionRegionUpperLimits(dstDimRgn, dstUpperLimits);  
513    
514          return; // end of recursion          return; // returning from deepest level of function recursion
515      }      }
516    
517      Dimensions::iterator itDimension = dims.begin();      // Copying n dimensions requires n nested loops. That's why this function
518        // is calling itself recursively to provide the required amount of nested
519        // loops. With each call it pops from argument 'dims' and pushes to
520        // argument 'dimCase'.
521    
522        Dimensions::iterator itDimension = dims.begin();
523      gig::dimension_t type = itDimension->first;      gig::dimension_t type = itDimension->first;
524      DimensionZones  zones = itDimension->second;      DimensionZones  zones = itDimension->second;
   
525      dims.erase(itDimension);      dims.erase(itDimension);
526    
527      int iZone = 0;      int iZone = 0;
# Line 450  static void copyDimensionRegions(gig::Re Line 531  static void copyDimensionRegions(gig::Re
531          DLS::range_t zoneRange = *itZone;          DLS::range_t zoneRange = *itZone;
532          gig::dimension_def_t* def = outRgn->GetDimensionDefinition(type);          gig::dimension_def_t* def = outRgn->GetDimensionDefinition(type);
533          dimCase[type] = (def->split_type == gig::split_type_bit) ? iZone : zoneRange.low;          dimCase[type] = (def->split_type == gig::split_type_bit) ? iZone : zoneRange.low;
534    
535          // recurse until 'dims' is exhausted (and dimCase filled up with concrete value)          // recurse until 'dims' is exhausted (and dimCase filled up with concrete value)
536          copyDimensionRegions(outRgn, inRgn, dims, iDstLayer, iSrcLayer, dimCase);          copyDimensionRegions(outRgn, inRgn, dims, iDstLayer, iSrcLayer, dimCase, schedule);
537        }
538    
539        // if current function call is the (very first) entry point ...
540        if (isHighestLevelOfRecursion) {
541            // ... then perform all scheduled DimensionRegion copy operations
542            for (uint i = 0; i < schedule->size(); ++i) {
543                CopyAssignSchedEntry& e = (*schedule)[i];
544    
545                // backup the target DimensionRegion's current dimension zones upper
546                // limits (because the target DimensionRegion's upper limits are
547                // already defined correctly since calling AddDimension(), and the
548                // CopyAssign() call next, will overwrite those upper limits
549                // unfortunately
550                DimensionRegionUpperLimits dstUpperLimits = getDimensionRegionUpperLimits(e.dst);
551                DimensionRegionUpperLimits srcUpperLimits = getDimensionRegionUpperLimits(e.src);
552    
553                // now actually copy over the current DimensionRegion
554                const gig::Region* const origRgn = e.dst->GetParent(); // just for sanity check below
555                e.dst->CopyAssign(e.src);
556                assert(origRgn == e.dst->GetParent()); // if gigedit is crashing here, then you must update libgig (to at least SVN r2547, v3.3.0.svn10)
557    
558                // restore all original dimension zone upper limits except of the
559                // velocity dimension, because the velocity dimension zone sizes are
560                // allowed to differ for individual DimensionRegions in gig v3
561                // format
562                if (srcUpperLimits.count(gig::dimension_velocity)) {
563                    assert(dstUpperLimits.count(gig::dimension_velocity));
564                    dstUpperLimits[gig::dimension_velocity] =
565                        (e.velocityZone >= e.totalSrcVelocityZones)
566                            ? 127 : srcUpperLimits[gig::dimension_velocity];
567                }
568                restoreDimensionRegionUpperLimits(e.dst, dstUpperLimits);
569            }
570            delete schedule;
571      }      }
572  }  }
573    
# Line 487  static void combineInstruments(std::vect Line 603  static void combineInstruments(std::vect
603    
604      // create a new output instrument      // create a new output instrument
605      gig::Instrument* outInstr = gig->AddInstrument();      gig::Instrument* outInstr = gig->AddInstrument();
606      outInstr->pInfo->Name = "NEW COMBINATION";      outInstr->pInfo->Name = _("NEW COMBINATION");
607    
608      // Distinguishing in the following code block between 'horizontal' and      // Distinguishing in the following code block between 'horizontal' and
609      // 'vertical' regions. The 'horizontal' ones are meant to be the key ranges      // 'vertical' regions. The 'horizontal' ones are meant to be the key ranges
# Line 589  CombineInstrumentsDialog::CombineInstrum Line 705  CombineInstrumentsDialog::CombineInstrum
705    
706      m_refTreeModel = Gtk::ListStore::create(m_columns);      m_refTreeModel = Gtk::ListStore::create(m_columns);
707      m_treeView.set_model(m_refTreeModel);      m_treeView.set_model(m_refTreeModel);
708      //m_treeView.set_tooltip_text(_("asdf"));      m_treeView.set_tooltip_text(_(
709            "Use SHIFT + left click or CTRL + left click to select the instruments "
710            "you want to combine."
711        ));
712      m_treeView.append_column("Instrument", m_columns.m_col_name);      m_treeView.append_column("Instrument", m_columns.m_col_name);
713      m_treeView.set_headers_visible(false);      m_treeView.set_headers_visible(false);
714      m_treeView.get_selection()->set_mode(Gtk::SELECTION_MULTIPLE);      m_treeView.get_selection()->set_mode(Gtk::SELECTION_MULTIPLE);
# Line 639  CombineInstrumentsDialog::CombineInstrum Line 758  CombineInstrumentsDialog::CombineInstrum
758      );      );
759    
760      show_all_children();      show_all_children();
761    
762        // show a warning to user if he uses a .gig in v2 format
763        if (gig->pVersion->major < 3) {
764            Glib::ustring txt = _(
765                "You are currently using a .gig file in old v2 format. The current "
766                "combine algorithm will most probably fail trying to combine "
767                "instruments in this old format. So better save the file in new v3 "
768                "format before trying to combine your instruments."
769            );
770            Gtk::MessageDialog msg(*this, txt, false, Gtk::MESSAGE_WARNING);
771            msg.run();
772        }
773  }  }
774    
775  void CombineInstrumentsDialog::combineSelectedInstruments() {  void CombineInstrumentsDialog::combineSelectedInstruments() {

Legend:
Removed from v.2548  
changed lines
  Added in v.2550

  ViewVC Help
Powered by ViewVC