15 |
#include <set> |
#include <set> |
16 |
#include <iostream> |
#include <iostream> |
17 |
#include <assert.h> |
#include <assert.h> |
18 |
|
#include <stdarg.h> |
19 |
|
#include <string.h> |
20 |
|
|
21 |
#include <glibmm/ustring.h> |
#include <glibmm/ustring.h> |
22 |
#include <gtkmm/stock.h> |
#include <gtkmm/stock.h> |
34 |
|
|
35 |
typedef std::map<gig::dimension_t, int> DimensionRegionUpperLimits; |
typedef std::map<gig::dimension_t, int> DimensionRegionUpperLimits; |
36 |
|
|
37 |
typedef std::map<gig::DimensionRegion*, DimensionZones> VelocityZones; |
typedef std::set<Glib::ustring> Warnings; |
38 |
|
|
39 |
|
/////////////////////////////////////////////////////////////////////////// |
40 |
|
// private static data |
41 |
|
|
42 |
|
static Warnings g_warnings; |
43 |
|
|
44 |
/////////////////////////////////////////////////////////////////////////// |
/////////////////////////////////////////////////////////////////////////// |
45 |
// private functions |
// private functions |
56 |
#endif |
#endif |
57 |
|
|
58 |
/** |
/** |
59 |
|
* Store a warning message that shall be stored and displayed to the user as a |
60 |
|
* list of warnings after the overall operation has finished. Duplicate warning |
61 |
|
* messages are automatically eliminated. |
62 |
|
*/ |
63 |
|
inline void addWarning(const char* fmt, ...) { |
64 |
|
va_list arg; |
65 |
|
va_start(arg, fmt); |
66 |
|
const int SZ = 255 + strlen(fmt); |
67 |
|
char* buf = new char[SZ]; |
68 |
|
vsnprintf(buf, SZ, fmt, arg); |
69 |
|
Glib::ustring s = buf; |
70 |
|
delete [] buf; |
71 |
|
va_end(arg); |
72 |
|
std::cerr << _("WARNING:") << " " << s << std::endl << std::flush; |
73 |
|
g_warnings.insert(s); |
74 |
|
} |
75 |
|
|
76 |
|
/** |
77 |
* If the two ranges overlap, then this function returns the smallest point |
* If the two ranges overlap, then this function returns the smallest point |
78 |
* within that overlapping zone. If the two ranges do not overlap, then this |
* within that overlapping zone. If the two ranges do not overlap, then this |
79 |
* function will return -1 instead. |
* function will return -1 instead. |
158 |
std::vector<gig::Region*> v = getAllRegionsWhichOverlapRange(instr, range); |
std::vector<gig::Region*> v = getAllRegionsWhichOverlapRange(instr, range); |
159 |
if (v.empty()) continue; |
if (v.empty()) continue; |
160 |
if (v.size() > 1) { |
if (v.size() > 1) { |
161 |
std::cerr << "WARNING: More than one region found!" << std::endl; |
addWarning("More than one region found!"); |
162 |
} |
} |
163 |
group[instr] = v[0]; |
group[instr] = v[0]; |
164 |
} |
} |
202 |
if (!group.empty()) |
if (!group.empty()) |
203 |
groups[range] = group; |
groups[range] = group; |
204 |
else |
else |
205 |
std::cerr << "WARNING: empty region group!" << std::endl; |
addWarning("Empty region group!"); |
206 |
} |
} |
207 |
|
|
208 |
return groups; |
return groups; |
278 |
} |
} |
279 |
|
|
280 |
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) { |
281 |
|
#if DEBUG_COMBINE_INSTRUMENTS |
282 |
|
printf("dimvalues = { "); |
283 |
|
fflush(stdout); |
284 |
|
#endif |
285 |
for (DimensionCase::iterator it = dimCase.begin(); it != dimCase.end(); ++it) { |
for (DimensionCase::iterator it = dimCase.begin(); it != dimCase.end(); ++it) { |
286 |
gig::dimension_t type = it->first; |
gig::dimension_t type = it->first; |
287 |
int iDimIndex = getDimensionIndex(type, rgn); |
int iDimIndex = getDimensionIndex(type, rgn); |
288 |
if (bShouldHaveAllDimensionsPassed) assert(iDimIndex >= 0); |
if (bShouldHaveAllDimensionsPassed) assert(iDimIndex >= 0); |
289 |
else if (iDimIndex < 0) continue; |
else if (iDimIndex < 0) continue; |
290 |
values[iDimIndex] = it->second; |
values[iDimIndex] = it->second; |
291 |
|
#if DEBUG_COMBINE_INSTRUMENTS |
292 |
|
printf("%x=%d, ", type, it->second); |
293 |
|
#endif |
294 |
} |
} |
295 |
|
#if DEBUG_COMBINE_INSTRUMENTS |
296 |
|
printf("\n"); |
297 |
|
#endif |
298 |
} |
} |
299 |
|
|
300 |
static DimensionRegionUpperLimits getDimensionRegionUpperLimits(gig::DimensionRegion* dimRgn) { |
static DimensionRegionUpperLimits getDimensionRegionUpperLimits(gig::DimensionRegion* dimRgn) { |
369 |
int iBaseBits = baseBits(type, rgn); |
int iBaseBits = baseBits(type, rgn); |
370 |
int mask = ~(((1 << def.bits) - 1) << iBaseBits); |
int mask = ~(((1 << def.bits) - 1) << iBaseBits); |
371 |
|
|
372 |
|
#if DEBUG_COMBINE_INSTRUMENTS |
373 |
|
printf("velo zones { "); |
374 |
|
fflush(stdout); |
375 |
|
#endif |
376 |
int iLow = 0; |
int iLow = 0; |
377 |
for (int z = 0; z < def.zones; ++z) { |
for (int z = 0; z < def.zones; ++z) { |
378 |
gig::DimensionRegion* dimRgn2 = |
gig::DimensionRegion* dimRgn2 = |
379 |
rgn->pDimensionRegions[ (iDimRgn & mask) | ( z << iBaseBits) ]; |
rgn->pDimensionRegions[ (iDimRgn & mask) | ( z << iBaseBits) ]; |
380 |
int iHigh = dimRgn2->DimensionUpperLimits[iDimension]; |
int iHigh = dimRgn2->DimensionUpperLimits[iDimension]; |
381 |
DLS::range_t range = { iLow, iHigh}; |
DLS::range_t range = { iLow, iHigh}; |
382 |
|
#if DEBUG_COMBINE_INSTRUMENTS |
383 |
|
printf("%d..%d, ", iLow, iHigh); |
384 |
|
fflush(stdout); |
385 |
|
#endif |
386 |
zones.push_back(range); |
zones.push_back(range); |
387 |
iLow = iHigh + 1; |
iLow = iHigh + 1; |
388 |
} |
} |
389 |
|
#if DEBUG_COMBINE_INSTRUMENTS |
390 |
|
printf("}\n"); |
391 |
|
#endif |
392 |
return zones; |
return zones; |
393 |
} |
} |
394 |
|
|
395 |
static VelocityZones getVelocityZones(gig::Region* rgn) { |
struct CopyAssignSchedEntry { |
396 |
VelocityZones zones; |
gig::DimensionRegion* src; |
397 |
for (uint i = 0; i < rgn->DimensionRegions; ++i) { |
gig::DimensionRegion* dst; |
398 |
gig::DimensionRegion* dimRgn = rgn->pDimensionRegions[i]; |
int velocityZone; |
399 |
zones[dimRgn] = preciseDimensionZonesFor(gig::dimension_velocity, dimRgn); |
int totalSrcVelocityZones; |
400 |
} |
}; |
401 |
return zones; |
typedef std::vector<CopyAssignSchedEntry> CopyAssignSchedule; |
|
} |
|
402 |
|
|
403 |
/** @brief Copy all DimensionRegions from source Region to target Region. |
/** @brief Copy all DimensionRegions from source Region to target Region. |
404 |
* |
* |
415 |
* |
* |
416 |
* @param outRgn - where the dimension regions shall be copied to |
* @param outRgn - where the dimension regions shall be copied to |
417 |
* @param inRgn - all dimension regions that shall be copied from |
* @param inRgn - all dimension regions that shall be copied from |
418 |
* @param dims - dimension definitions of target region |
* @param dims - precise dimension definitions of target region |
419 |
* @param iDstLayer - layer number of destination region where the dimension |
* @param iDstLayer - layer index of destination region where the dimension |
420 |
* regions shall be copied to |
* regions shall be copied to |
421 |
* @param iSrcLayer - layer number of the source region where the dimension |
* @param iSrcLayer - layer index of the source region where the dimension |
422 |
* regions shall be copied from |
* regions shall be copied from |
|
* @param dstVelocityZones - all precise velocity zones for destination region |
|
|
* (since this information is stored on |
|
|
* DimensionRegion level and this function is |
|
|
* modifying target DimensionRegions, this |
|
|
* informations thus needs to be retrieved before |
|
|
* calling this function) |
|
423 |
* @param dimCase - just for internal purpose (function recursion), don't pass |
* @param dimCase - just for internal purpose (function recursion), don't pass |
424 |
* anything here, this function will call itself recursively |
* anything here, this function will call itself recursively |
425 |
* will fill this container with concrete dimension values for |
* will fill this container with concrete dimension values for |
426 |
* selecting the precise dimension regions during its task |
* selecting the precise dimension regions during its task |
427 |
|
* @param schedule - just for internal purpose (function recursion), don't pass |
428 |
|
anything here: list of all DimensionRegion copy operations |
429 |
|
* which is filled during the nested loops / recursions of |
430 |
|
* this function call, they will be peformed after all |
431 |
|
* function recursions have been completed |
432 |
*/ |
*/ |
433 |
static void copyDimensionRegions(gig::Region* outRgn, gig::Region* inRgn, Dimensions dims, int iDstLayer, int iSrcLayer, const VelocityZones& dstVelocityZones, DimensionCase dimCase = DimensionCase()) { |
static void copyDimensionRegions(gig::Region* outRgn, gig::Region* inRgn, Dimensions dims, int iDstLayer, int iSrcLayer, DimensionCase dimCase = DimensionCase(), CopyAssignSchedule* schedule = NULL) { |
434 |
if (dims.empty()) { // finally reached end of function recursion ... |
const bool isHighestLevelOfRecursion = !schedule; |
435 |
|
|
436 |
|
if (isHighestLevelOfRecursion) |
437 |
|
schedule = new CopyAssignSchedule; |
438 |
|
|
439 |
|
if (dims.empty()) { // reached deepest level of function recursion ... |
440 |
|
CopyAssignSchedEntry e; |
441 |
|
|
442 |
// resolve the respective source & destination DimensionRegion ... |
// resolve the respective source & destination DimensionRegion ... |
443 |
uint srcDimValues[8] = {}; |
uint srcDimValues[8] = {}; |
444 |
uint dstDimValues[8] = {}; |
uint dstDimValues[8] = {}; |
447 |
srcDimCase[gig::dimension_layer] = iSrcLayer; |
srcDimCase[gig::dimension_layer] = iSrcLayer; |
448 |
dstDimCase[gig::dimension_layer] = iDstLayer; |
dstDimCase[gig::dimension_layer] = iDstLayer; |
449 |
|
|
450 |
|
#if DEBUG_COMBINE_INSTRUMENTS |
451 |
|
printf("-------------------------------\n"); |
452 |
|
#endif |
453 |
|
|
454 |
// first select source & target dimension region with an arbitrary |
// first select source & target dimension region with an arbitrary |
455 |
// velocity split zone, to get access to the precise individual velocity |
// velocity split zone, to get access to the precise individual velocity |
456 |
// split zone sizes (if there is actually a velocity dimension at all, |
// split zone sizes (if there is actually a velocity dimension at all, |
457 |
// otherwise we already select the desired source & target dimension |
// otherwise we already select the desired source & target dimension |
458 |
// region here) |
// region here) |
459 |
|
#if DEBUG_COMBINE_INSTRUMENTS |
460 |
|
printf("src "); fflush(stdout); |
461 |
|
#endif |
462 |
fillDimValues(srcDimValues, srcDimCase, inRgn, false); |
fillDimValues(srcDimValues, srcDimCase, inRgn, false); |
463 |
|
#if DEBUG_COMBINE_INSTRUMENTS |
464 |
|
printf("dst "); fflush(stdout); |
465 |
|
#endif |
466 |
fillDimValues(dstDimValues, dstDimCase, outRgn, true); |
fillDimValues(dstDimValues, dstDimCase, outRgn, true); |
467 |
gig::DimensionRegion* srcDimRgn = inRgn->GetDimensionRegionByValue(srcDimValues); |
gig::DimensionRegion* srcDimRgn = inRgn->GetDimensionRegionByValue(srcDimValues); |
468 |
gig::DimensionRegion* dstDimRgn = outRgn->GetDimensionRegionByValue(dstDimValues); |
gig::DimensionRegion* dstDimRgn = outRgn->GetDimensionRegionByValue(dstDimValues); |
469 |
#if DEBUG_COMBINE_INSTRUMENTS |
#if DEBUG_COMBINE_INSTRUMENTS |
470 |
|
printf("iDstLayer=%d iSrcLayer=%d\n", iDstLayer, iSrcLayer); |
471 |
printf("srcDimRgn=%lx dstDimRgn=%lx\n", (uint64_t)srcDimRgn, (uint64_t)dstDimRgn); |
printf("srcDimRgn=%lx dstDimRgn=%lx\n", (uint64_t)srcDimRgn, (uint64_t)dstDimRgn); |
472 |
|
printf("srcSample='%s' dstSample='%s'\n", |
473 |
|
(!srcDimRgn->pSample ? "NULL" : srcDimRgn->pSample->pInfo->Name.c_str()), |
474 |
|
(!dstDimRgn->pSample ? "NULL" : dstDimRgn->pSample->pInfo->Name.c_str()) |
475 |
|
); |
476 |
#endif |
#endif |
477 |
|
|
478 |
|
assert(srcDimRgn->GetParent() == inRgn); |
479 |
|
assert(dstDimRgn->GetParent() == outRgn); |
480 |
|
|
481 |
// now that we have access to the precise velocity split zone upper |
// now that we have access to the precise velocity split zone upper |
482 |
// limits, we can select the actual source & destination dimension |
// limits, we can select the actual source & destination dimension |
483 |
// regions we need to copy (assuming that source or target region has |
// regions we need to copy (assuming that source or target region has |
484 |
// a velocity dimension) |
// a velocity dimension) |
485 |
if (outRgn->GetDimensionDefinition(gig::dimension_velocity)) { |
if (outRgn->GetDimensionDefinition(gig::dimension_velocity)) { |
486 |
// re-select target dimension region |
// re-select target dimension region (with correct velocity zone) |
487 |
assert(dstVelocityZones.find(dstDimRgn) != dstVelocityZones.end()); |
DimensionZones dstZones = preciseDimensionZonesFor(gig::dimension_velocity, dstDimRgn); |
|
DimensionZones dstZones = dstVelocityZones.find(dstDimRgn)->second; |
|
488 |
assert(dstZones.size() > 1); |
assert(dstZones.size() > 1); |
489 |
int iZoneIndex = dstDimCase[gig::dimension_velocity]; |
int iZoneIndex = dstDimCase[gig::dimension_velocity]; |
490 |
|
e.velocityZone = iZoneIndex; |
491 |
#if DEBUG_COMBINE_INSTRUMENTS |
#if DEBUG_COMBINE_INSTRUMENTS |
492 |
printf("dst velocity zone: %d/%d\n", iZoneIndex, dstZones.size()); |
printf("dst velocity zone: %d/%d\n", iZoneIndex, (int)dstZones.size()); |
493 |
#endif |
#endif |
494 |
assert(iZoneIndex < dstZones.size()); |
assert(uint(iZoneIndex) < dstZones.size()); |
495 |
dstDimCase[gig::dimension_velocity] = dstZones[iZoneIndex].low; // arbitrary value between low and high |
dstDimCase[gig::dimension_velocity] = dstZones[iZoneIndex].low; // arbitrary value between low and high |
496 |
#if DEBUG_COMBINE_INSTRUMENTS |
#if DEBUG_COMBINE_INSTRUMENTS |
497 |
printf("dst velocity value = %d\n", dstDimCase[gig::dimension_velocity]); |
printf("dst velocity value = %d\n", dstDimCase[gig::dimension_velocity]); |
498 |
|
printf("dst refilled "); fflush(stdout); |
499 |
#endif |
#endif |
500 |
fillDimValues(dstDimValues, dstDimCase, outRgn, true); |
fillDimValues(dstDimValues, dstDimCase, outRgn, true); |
501 |
dstDimRgn = outRgn->GetDimensionRegionByValue(dstDimValues); |
dstDimRgn = outRgn->GetDimensionRegionByValue(dstDimValues); |
502 |
#if DEBUG_COMBINE_INSTRUMENTS |
#if DEBUG_COMBINE_INSTRUMENTS |
503 |
printf("reselected dstDimRgn=%lx\n", (uint64_t)dstDimRgn); |
printf("reselected dstDimRgn=%lx\n", (uint64_t)dstDimRgn); |
504 |
|
printf("dstSample='%s'\n", |
505 |
|
(!dstDimRgn->pSample ? "NULL" : dstDimRgn->pSample->pInfo->Name.c_str()) |
506 |
|
); |
507 |
#endif |
#endif |
508 |
|
|
509 |
// re-select source dimension region |
// re-select source dimension region with correct velocity zone |
510 |
// (if it has a velocity dimension) |
// (if it has a velocity dimension that is) |
511 |
if (inRgn->GetDimensionDefinition(gig::dimension_velocity)) { |
if (inRgn->GetDimensionDefinition(gig::dimension_velocity)) { |
512 |
DimensionZones srcZones = preciseDimensionZonesFor(gig::dimension_velocity, srcDimRgn); |
DimensionZones srcZones = preciseDimensionZonesFor(gig::dimension_velocity, srcDimRgn); |
513 |
assert(srcZones.size() > 1); |
e.totalSrcVelocityZones = srcZones.size(); |
514 |
if (iZoneIndex >= srcZones.size()) |
assert(srcZones.size() > 0); |
515 |
iZoneIndex = srcZones.size(); |
if (srcZones.size() <= 1) { |
516 |
|
addWarning("Input region has a velocity dimension with only ONE zone!"); |
517 |
|
} |
518 |
|
if (uint(iZoneIndex) >= srcZones.size()) |
519 |
|
iZoneIndex = srcZones.size() - 1; |
520 |
srcDimCase[gig::dimension_velocity] = srcZones[iZoneIndex].low; // same zone as used above for target dimension region (no matter what the precise zone ranges are) |
srcDimCase[gig::dimension_velocity] = srcZones[iZoneIndex].low; // same zone as used above for target dimension region (no matter what the precise zone ranges are) |
521 |
|
#if DEBUG_COMBINE_INSTRUMENTS |
522 |
|
printf("src refilled "); fflush(stdout); |
523 |
|
#endif |
524 |
fillDimValues(srcDimValues, srcDimCase, inRgn, false); |
fillDimValues(srcDimValues, srcDimCase, inRgn, false); |
525 |
srcDimRgn = inRgn->GetDimensionRegionByValue(srcDimValues); |
srcDimRgn = inRgn->GetDimensionRegionByValue(srcDimValues); |
526 |
#if DEBUG_COMBINE_INSTRUMENTS |
#if DEBUG_COMBINE_INSTRUMENTS |
527 |
printf("reselected srcDimRgn=%lx\n", (uint64_t)srcDimRgn); |
printf("reselected srcDimRgn=%lx\n", (uint64_t)srcDimRgn); |
528 |
|
printf("srcSample='%s'\n", |
529 |
|
(!srcDimRgn->pSample ? "NULL" : srcDimRgn->pSample->pInfo->Name.c_str()) |
530 |
|
); |
531 |
#endif |
#endif |
532 |
} |
} |
533 |
} |
} |
534 |
|
|
535 |
// backup the target DimensionRegion's current dimension zones upper |
// Schedule copy opertion of source -> target DimensionRegion for the |
536 |
// limits (because the target DimensionRegion's upper limits are already |
// time after all nested loops have been traversed. We have to postpone |
537 |
// defined correctly since calling AddDimension(), and the CopyAssign() |
// the actual copy operations this way, because otherwise it would |
538 |
// call next, will overwrite those upper limits unfortunately |
// overwrite informations inside the destination DimensionRegion object |
539 |
DimensionRegionUpperLimits dstUpperLimits = getDimensionRegionUpperLimits(dstDimRgn); |
// that we need to read in the code block above. |
540 |
DimensionRegionUpperLimits srcUpperLimits = getDimensionRegionUpperLimits(srcDimRgn); |
e.src = srcDimRgn; |
541 |
|
e.dst = dstDimRgn; |
542 |
// 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); |
|
543 |
|
|
544 |
return; // end of recursion |
return; // returning from deepest level of function recursion |
545 |
} |
} |
546 |
|
|
547 |
// Copying n dimensions requires n nested loops. That's why this function |
// Copying n dimensions requires n nested loops. That's why this function |
550 |
// argument 'dimCase'. |
// argument 'dimCase'. |
551 |
|
|
552 |
Dimensions::iterator itDimension = dims.begin(); |
Dimensions::iterator itDimension = dims.begin(); |
|
|
|
553 |
gig::dimension_t type = itDimension->first; |
gig::dimension_t type = itDimension->first; |
554 |
DimensionZones zones = itDimension->second; |
DimensionZones zones = itDimension->second; |
|
|
|
555 |
dims.erase(itDimension); |
dims.erase(itDimension); |
556 |
|
|
557 |
int iZone = 0; |
int iZone = 0; |
561 |
DLS::range_t zoneRange = *itZone; |
DLS::range_t zoneRange = *itZone; |
562 |
gig::dimension_def_t* def = outRgn->GetDimensionDefinition(type); |
gig::dimension_def_t* def = outRgn->GetDimensionDefinition(type); |
563 |
dimCase[type] = (def->split_type == gig::split_type_bit) ? iZone : zoneRange.low; |
dimCase[type] = (def->split_type == gig::split_type_bit) ? iZone : zoneRange.low; |
564 |
|
|
565 |
// recurse until 'dims' is exhausted (and dimCase filled up with concrete value) |
// recurse until 'dims' is exhausted (and dimCase filled up with concrete value) |
566 |
copyDimensionRegions(outRgn, inRgn, dims, iDstLayer, iSrcLayer, dstVelocityZones, dimCase); |
copyDimensionRegions(outRgn, inRgn, dims, iDstLayer, iSrcLayer, dimCase, schedule); |
567 |
|
} |
568 |
|
|
569 |
|
// if current function call is the (very first) entry point ... |
570 |
|
if (isHighestLevelOfRecursion) { |
571 |
|
// ... then perform all scheduled DimensionRegion copy operations |
572 |
|
for (uint i = 0; i < schedule->size(); ++i) { |
573 |
|
CopyAssignSchedEntry& e = (*schedule)[i]; |
574 |
|
|
575 |
|
// backup the target DimensionRegion's current dimension zones upper |
576 |
|
// limits (because the target DimensionRegion's upper limits are |
577 |
|
// already defined correctly since calling AddDimension(), and the |
578 |
|
// CopyAssign() call next, will overwrite those upper limits |
579 |
|
// unfortunately |
580 |
|
DimensionRegionUpperLimits dstUpperLimits = getDimensionRegionUpperLimits(e.dst); |
581 |
|
DimensionRegionUpperLimits srcUpperLimits = getDimensionRegionUpperLimits(e.src); |
582 |
|
|
583 |
|
// now actually copy over the current DimensionRegion |
584 |
|
const gig::Region* const origRgn = e.dst->GetParent(); // just for sanity check below |
585 |
|
e.dst->CopyAssign(e.src); |
586 |
|
assert(origRgn == e.dst->GetParent()); // if gigedit is crashing here, then you must update libgig (to at least SVN r2547, v3.3.0.svn10) |
587 |
|
|
588 |
|
// restore all original dimension zone upper limits except of the |
589 |
|
// velocity dimension, because the velocity dimension zone sizes are |
590 |
|
// allowed to differ for individual DimensionRegions in gig v3 |
591 |
|
// format |
592 |
|
if (srcUpperLimits.count(gig::dimension_velocity)) { |
593 |
|
if (!dstUpperLimits.count(gig::dimension_velocity)) { |
594 |
|
addWarning("Source instrument seems to have a velocity dimension whereas new target instrument doesn't!"); |
595 |
|
} else { |
596 |
|
dstUpperLimits[gig::dimension_velocity] = |
597 |
|
(e.velocityZone >= e.totalSrcVelocityZones) |
598 |
|
? 127 : srcUpperLimits[gig::dimension_velocity]; |
599 |
|
} |
600 |
|
} |
601 |
|
restoreDimensionRegionUpperLimits(e.dst, dstUpperLimits); |
602 |
|
} |
603 |
|
delete schedule; |
604 |
} |
} |
605 |
} |
} |
606 |
|
|
651 |
{ |
{ |
652 |
gig::Region* outRgn = outInstr->AddRegion(); |
gig::Region* outRgn = outInstr->AddRegion(); |
653 |
outRgn->SetKeyRange(itGroup->first.low, itGroup->first.high); |
outRgn->SetKeyRange(itGroup->first.low, itGroup->first.high); |
654 |
|
#if DEBUG_COMBINE_INSTRUMENTS |
655 |
|
printf("---> Start target region %d..%d\n", itGroup->first.low, itGroup->first.high); |
656 |
|
#endif |
657 |
|
|
658 |
// detect the total amount of layers required to build up this combi |
// detect the total amount of layers required to build up this combi |
659 |
// for current key range |
// for current key range |
664 |
gig::Region* inRgn = itRgn->second; |
gig::Region* inRgn = itRgn->second; |
665 |
iTotalLayers += inRgn->Layers; |
iTotalLayers += inRgn->Layers; |
666 |
} |
} |
667 |
|
#if DEBUG_COMBINE_INSTRUMENTS |
668 |
|
printf("Required total layers: %d\n", iTotalLayers); |
669 |
|
#endif |
670 |
|
|
671 |
// create all required dimensions for this output region |
// create all required dimensions for this output region |
672 |
// (except the layer dimension, which we create as next step) |
// (except the layer dimension, which we create as next step) |
673 |
Dimensions dims = getDimensionsForRegionGroup(itGroup->second); |
Dimensions dims = getDimensionsForRegionGroup(itGroup->second); |
|
for (Dimensions::iterator itDim = dims.begin(); |
|
|
itDim != dims.end(); ++itDim) |
|
674 |
{ |
{ |
675 |
if (itDim->first == gig::dimension_layer) continue; |
std::vector<gig::dimension_t> skipTheseDimensions; // used to prevent a misbehavior (i.e. crash) of the combine algorithm in case one of the source instruments has a dimension with only one zone, which is not standard conform |
676 |
|
|
677 |
gig::dimension_def_t def; |
for (Dimensions::iterator itDim = dims.begin(); |
678 |
def.dimension = itDim->first; // dimension type |
itDim != dims.end(); ++itDim) |
679 |
def.zones = itDim->second.size(); |
{ |
680 |
def.bits = zoneCountToBits(def.zones); |
// layer dimension is created separately in the next code block |
681 |
#if DEBUG_COMBINE_INSTRUMENTS |
// (outside of this loop) |
682 |
std::cout << "Adding new regular dimension type=" << std::hex << (int)def.dimension << std::dec << ", zones=" << (int)def.zones << ", bits=" << (int)def.bits << " ... " << std::flush; |
if (itDim->first == gig::dimension_layer) continue; |
683 |
#endif |
|
684 |
outRgn->AddDimension(&def); |
gig::dimension_def_t def; |
685 |
#if DEBUG_COMBINE_INSTRUMENTS |
def.dimension = itDim->first; // dimension type |
686 |
std::cout << "OK" << std::endl << std::flush; |
def.zones = itDim->second.size(); |
687 |
#endif |
def.bits = zoneCountToBits(def.zones); |
688 |
|
if (def.zones < 2) { |
689 |
|
addWarning( |
690 |
|
"Attempt to create dimension with type=0x%x with only " |
691 |
|
"ONE zone (because at least one of the source " |
692 |
|
"instruments seems to have such a velocity dimension " |
693 |
|
"with only ONE zone, which is odd)! Skipping this " |
694 |
|
"dimension for now.", |
695 |
|
(int)itDim->first |
696 |
|
); |
697 |
|
skipTheseDimensions.push_back(itDim->first); |
698 |
|
continue; |
699 |
|
} |
700 |
|
#if DEBUG_COMBINE_INSTRUMENTS |
701 |
|
std::cout << "Adding new regular dimension type=" << std::hex << (int)def.dimension << std::dec << ", zones=" << (int)def.zones << ", bits=" << (int)def.bits << " ... " << std::flush; |
702 |
|
#endif |
703 |
|
outRgn->AddDimension(&def); |
704 |
|
#if DEBUG_COMBINE_INSTRUMENTS |
705 |
|
std::cout << "OK" << std::endl << std::flush; |
706 |
|
#endif |
707 |
|
} |
708 |
|
// prevent the following dimensions to be processed further below |
709 |
|
// (since the respective dimension was not created above) |
710 |
|
for (int i = 0; i < skipTheseDimensions.size(); ++i) |
711 |
|
dims.erase(skipTheseDimensions[i]); |
712 |
} |
} |
713 |
|
|
714 |
// create the layer dimension (if necessary for current key range) |
// create the layer dimension (if necessary for current key range) |
732 |
itRgn != itGroup->second.end(); ++itRgn) // iterate over 'vertical' / source regions ... |
itRgn != itGroup->second.end(); ++itRgn) // iterate over 'vertical' / source regions ... |
733 |
{ |
{ |
734 |
gig::Region* inRgn = itRgn->second; |
gig::Region* inRgn = itRgn->second; |
735 |
VelocityZones dstVelocityZones = getVelocityZones(outRgn); |
#if DEBUG_COMBINE_INSTRUMENTS |
736 |
|
printf("[source region of '%s']\n", inRgn->GetParent()->pInfo->Name.c_str()); |
737 |
|
#endif |
738 |
for (uint iSrcLayer = 0; iSrcLayer < inRgn->Layers; ++iSrcLayer, ++iDstLayer) { |
for (uint iSrcLayer = 0; iSrcLayer < inRgn->Layers; ++iSrcLayer, ++iDstLayer) { |
739 |
copyDimensionRegions(outRgn, inRgn, dims, iDstLayer, iSrcLayer, dstVelocityZones); |
copyDimensionRegions(outRgn, inRgn, dims, iDstLayer, iSrcLayer); |
740 |
} |
} |
741 |
} |
} |
742 |
} |
} |
769 |
|
|
770 |
m_refTreeModel = Gtk::ListStore::create(m_columns); |
m_refTreeModel = Gtk::ListStore::create(m_columns); |
771 |
m_treeView.set_model(m_refTreeModel); |
m_treeView.set_model(m_refTreeModel); |
772 |
//m_treeView.set_tooltip_text(_("asdf")); |
m_treeView.set_tooltip_text(_( |
773 |
|
"Use SHIFT + left click or CTRL + left click to select the instruments " |
774 |
|
"you want to combine." |
775 |
|
)); |
776 |
m_treeView.append_column("Instrument", m_columns.m_col_name); |
m_treeView.append_column("Instrument", m_columns.m_col_name); |
777 |
m_treeView.set_headers_visible(false); |
m_treeView.set_headers_visible(false); |
778 |
m_treeView.get_selection()->set_mode(Gtk::SELECTION_MULTIPLE); |
m_treeView.get_selection()->set_mode(Gtk::SELECTION_MULTIPLE); |
822 |
); |
); |
823 |
|
|
824 |
show_all_children(); |
show_all_children(); |
825 |
|
|
826 |
|
// show a warning to user if he uses a .gig in v2 format |
827 |
|
if (gig->pVersion->major < 3) { |
828 |
|
Glib::ustring txt = _( |
829 |
|
"You are currently using a .gig file in old v2 format. The current " |
830 |
|
"combine algorithm will most probably fail trying to combine " |
831 |
|
"instruments in this old format. So better save the file in new v3 " |
832 |
|
"format before trying to combine your instruments." |
833 |
|
); |
834 |
|
Gtk::MessageDialog msg(*this, txt, false, Gtk::MESSAGE_WARNING); |
835 |
|
msg.run(); |
836 |
|
} |
837 |
} |
} |
838 |
|
|
839 |
void CombineInstrumentsDialog::combineSelectedInstruments() { |
void CombineInstrumentsDialog::combineSelectedInstruments() { |
850 |
instruments.push_back(instrument); |
instruments.push_back(instrument); |
851 |
} |
} |
852 |
|
|
853 |
|
g_warnings.clear(); |
854 |
|
|
855 |
try { |
try { |
856 |
combineInstruments(instruments, m_gig, m_newCombinedInstrument); |
combineInstruments(instruments, m_gig, m_newCombinedInstrument); |
857 |
} catch (RIFF::Exception e) {; |
} catch (RIFF::Exception e) {; |
858 |
Gtk::MessageDialog msg(*this, e.Message, false, Gtk::MESSAGE_ERROR); |
Gtk::MessageDialog msg(*this, e.Message, false, Gtk::MESSAGE_ERROR); |
859 |
msg.run(); |
msg.run(); |
860 |
return; |
return; |
861 |
|
} catch (...) { |
862 |
|
Glib::ustring txt = _("An unknown exception occurred!"); |
863 |
|
Gtk::MessageDialog msg(*this, txt, false, Gtk::MESSAGE_ERROR); |
864 |
|
msg.run(); |
865 |
|
return; |
866 |
|
} |
867 |
|
|
868 |
|
if (!g_warnings.empty()) { |
869 |
|
Glib::ustring txt = _( |
870 |
|
"Combined instrument was created successfully, but there were warnings:" |
871 |
|
); |
872 |
|
txt += "\n\n"; |
873 |
|
for (Warnings::const_iterator itWarn = g_warnings.begin(); |
874 |
|
itWarn != g_warnings.end(); ++itWarn) |
875 |
|
{ |
876 |
|
txt += "-> " + *itWarn + "\n"; |
877 |
|
} |
878 |
|
txt += "\n"; |
879 |
|
txt += _( |
880 |
|
"You might also want to check the console for further warnings and " |
881 |
|
"error messages." |
882 |
|
); |
883 |
|
Gtk::MessageDialog msg(*this, txt, false, Gtk::MESSAGE_WARNING); |
884 |
|
msg.run(); |
885 |
} |
} |
886 |
|
|
887 |
// no error occurred |
// no error occurred |