SampleDisplay.cc
上传用户:weiliju62
上传日期:2007-01-06
资源大小:619k
文件大小:31k
源码类别:

SCSI/ASPI

开发平台:

MultiPlatform

  1. /*  cdrdao - write audio CD-Rs in disc-at-once mode
  2.  *
  3.  *  Copyright (C) 1998  Andreas Mueller <mueller@daneb.ping.de>
  4.  *
  5.  *  This program is free software; you can redistribute it and/or modify
  6.  *  it under the terms of the GNU General Public License as published by
  7.  *  the Free Software Foundation; either version 2 of the License, or
  8.  *  (at your option) any later version.
  9.  *
  10.  *  This program is distributed in the hope that it will be useful,
  11.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13.  *  GNU General Public License for more details.
  14.  *
  15.  *  You should have received a copy of the GNU General Public License
  16.  *  along with this program; if not, write to the Free Software
  17.  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  18.  */
  19. /*
  20.  * $Log: SampleDisplay.cc,v $
  21.  * Revision 1.5  1999/08/07 16:27:28  mueller
  22.  * Applied patch from Yves Bastide:
  23.  * * prefixing member function names with their class name in connect_to_method
  24.  * * explicitly `const_cast'ing a cast to const
  25.  *
  26.  * Revision 1.4  1999/05/24 18:10:25  mueller
  27.  * Adapted to new reading interface of 'trackdb'.
  28.  *
  29.  * Revision 1.3  1999/01/30 19:45:43  mueller
  30.  * Fixes for compilation with Gtk-- 0.11.1.
  31.  *
  32.  * Revision 1.1  1998/11/20 18:55:22  mueller
  33.  * Initial revision
  34.  *
  35.  */
  36. static char rcsid[] = "$Id$";
  37. #include <stdio.h>
  38. #include <limits.h>
  39. #include <math.h>
  40. #include <assert.h>
  41. #include "TocEdit.h"
  42. #include "SampleDisplay.h"
  43. #include "SampleManager.h"
  44. #include "TrackManager.h"
  45. #include "Toc.h"
  46. #include "util.h"
  47. /* XPM data for track marker */
  48. #define TRACK_MARKER_XPM_WIDTH 9
  49. #define TRACK_MARKER_XPM_HEIGHT 12
  50. static gchar *TRACK_MARKER_XPM_DATA[] = {
  51.   "9 12 3 1",
  52.   "       c None",
  53.   "X      c #000000000000",
  54.   ".      c #FFFFFFFFFFFF",
  55.   "         ",
  56.   " XXXXXXX ",
  57.   " XXXXXXX ",
  58.   " XXXXXXX ",
  59.   " XXXXXXX ",
  60.   " XXXXXXX ",
  61.   " XXXXXXX ",
  62.   "  XXXXX  ",
  63.   "   XXX   ",
  64.   "    X    ",
  65.   "    X    ",
  66.   "    X    "};
  67. /* XPM data for index marker */
  68. static gchar *INDEX_MARKER_XPM_DATA[] = {
  69.   "9 12 3 1",
  70.   "       c None",
  71.   "X      c #000000000000",
  72.   ".      c #FFFFFFFFFFFF",
  73.   "         ",
  74.   " XXXXXXX ",
  75.   " X.....X ",
  76.   " X.....X ",
  77.   " X.....X ",
  78.   " X.....X ",
  79.   " X.....X ",
  80.   "  X...X  ",
  81.   "   X.X   ",
  82.   "    X    ",
  83.   "    X    ",
  84.   "    X    "};
  85. /* XPM data for extend track marker */
  86. static gchar *TRACK_EXTEND_XPM_DATA[] = {
  87.   "9 12 3 1",
  88.   "       c None",
  89.   "X      c #000000000000",
  90.   ".      c #FFFFFFFFFFFF",
  91.   "......XX.",
  92.   ".....XXX.",
  93.   "....XXXX.",
  94.   "...XXXXX.",
  95.   "..XXXXXX.",
  96.   ".XXXXXXX.",
  97.   "..XXXXXX.",
  98.   "...XXXXX.",
  99.   "....XXXX.",
  100.   ".....XXX.",
  101.   "......XX.",
  102.   "........."};
  103. /* XPM data for extend track marker */
  104. static gchar *INDEX_EXTEND_XPM_DATA[] = {
  105.   "9 12 3 1",
  106.   "       c None",
  107.   "X      c #000000000000",
  108.   ".      c #FFFFFFFFFFFF",
  109.   "......XX.",
  110.   ".....X.X.",
  111.   "....X..X.",
  112.   "...X...X.",
  113.   "..X....X.",
  114.   ".X.....X.",
  115.   "..X....X.",
  116.   "...X...X.",
  117.   "....X..X.",
  118.   ".....X.X.",
  119.   "......XX.",
  120.   "........."};
  121. SampleDisplay::SampleDisplay()
  122. {
  123.   adjustment_ = new Gtk_Adjustment(0.0, 0.0, 1.0);
  124.   connect_to_method(adjustment_->value_changed, this,
  125.     &SampleDisplay::scrollTo);
  126.   trackManager_ = NULL;
  127.   pixmap_ = NULL;
  128.   trackMarkerPixmap_ = indexMarkerPixmap_ = NULL;
  129.   trackMarkerSelectedPixmap_ = indexMarkerSelectedPixmap_ = NULL;
  130.   trackExtendPixmap_ = indexExtendPixmap_ = NULL;
  131.   drawGc_ = NULL;
  132.   timeTickFont_ = NULL;
  133.   trackMarkerFont_ = NULL;
  134.   width_ = height_ = chanHeight_ = lcenter_ = rcenter_ = 0;
  135.   timeLineHeight_ = timeLineY_ = 0;
  136.   timeTickWidth_ = 0;
  137.   timeTickSep_ = 20;
  138.   sampleStartX_ = sampleEndX_ = sampleWidthX_ = 0;
  139.   minSample_ = maxSample_ = resolution_ = 0;
  140.   tocEdit_ = NULL;
  141.   chanSep_ = 10;
  142.   cursorControlExtern_ = 0;
  143.   cursorDrawn_ = 0;
  144.   cursorX_ = 0;
  145.   markerSet_ = 0;
  146.   selectionSet_ = 0;
  147.   regionSet_ = 0;
  148.   dragMode_ = DRAG_NONE;
  149.   pickedTrackMarker_ = NULL;
  150.   selectedTrack_ = 0;
  151.   selectedIndex_ = 0;
  152.   connect_to_method(expose_event, this,
  153.                     &SampleDisplay::handle_expose_event);
  154.   connect_to_method(configure_event, this,
  155.                     &SampleDisplay::handle_configure_event);
  156.   connect_to_method(motion_notify_event, this,
  157.                     &SampleDisplay::handle_motion_notify_event);
  158.   connect_to_method(button_press_event, this,
  159.                     &SampleDisplay::handleButtonPressEvent);
  160.   connect_to_method(button_release_event, this,
  161.                     &SampleDisplay::handleButtonReleaseEvent);
  162.   connect_to_method(enter_notify_event, this,
  163.                     &SampleDisplay::handleEnterEvent);
  164.   connect_to_method(leave_notify_event, this,
  165.                     &SampleDisplay::handleLeaveEvent);
  166.   
  167.   //connect_to_method (motion_notify_event, this, &handle_motion_notify_event);
  168.   //connect_to_method (button_press_event, this, &handle_button_press_event);
  169.   set_events (GDK_EXPOSURE_MASK
  170.       | GDK_LEAVE_NOTIFY_MASK
  171.       | GDK_ENTER_NOTIFY_MASK
  172.       | GDK_BUTTON_PRESS_MASK
  173.       | GDK_BUTTON_RELEASE_MASK
  174.       | GDK_POINTER_MOTION_MASK
  175.       | GDK_POINTER_MOTION_HINT_MASK);
  176. }
  177. void SampleDisplay::setTocEdit(TocEdit *t)
  178. {
  179.   tocEdit_ = t;
  180.   Toc *toc = tocEdit_->toc();
  181.   markerSet_ = 0;
  182.   selectionSet_ = 0;
  183.   regionSet_ = 0;
  184.   minSample_ = 0;
  185.   if (toc->length().samples() > 0) {
  186.     maxSample_ = toc->length().samples() - 1;
  187.   }
  188.   else {
  189.     maxSample_ = 0;
  190.   }
  191. }
  192. void SampleDisplay::updateToc()
  193. {
  194.   Toc *toc = tocEdit_->toc();
  195.   if (toc->length().samples() == 0) {
  196.     minSample_ = maxSample_ = 0;
  197.   }
  198.   else {
  199.     if (maxSample_ >= toc->length().samples()) {
  200.       // adjust 'maxSample_' to reduced length
  201.       unsigned long len = maxSample_ - minSample_;
  202.       maxSample_ = toc->length().samples() - 1;
  203.       if (maxSample_ > len) {
  204. minSample_ = maxSample_ - len;
  205.       }
  206.       else {
  207. minSample_ = 0;
  208.       }
  209.     }
  210.   }
  211.   setView(minSample_, maxSample_);
  212. }
  213. void SampleDisplay::setView(unsigned long start, unsigned long end)
  214. {
  215.   Toc *toc = tocEdit_->toc();
  216.   if (end < start)
  217.     end = start;
  218.   unsigned long len = end - start + 1;
  219.   if (len < 3 && toc != NULL) {
  220.     end = start + 2;
  221.     if (end >= toc->length().samples()) {
  222.       if (toc->length().samples() != 0)
  223. end = toc->length().samples() - 1;
  224.       else
  225. end = 0;
  226.       if (end <= 2)
  227. start = 0;
  228.       else 
  229. start = end - 2;
  230.     }
  231.     
  232.     len = (end == 0 ? 0 : 3);
  233.   }
  234.   minSample_ = start;
  235.   maxSample_ = end;
  236.   updateSamples();
  237.   redraw(0, 0, width_, height_, 0);
  238.   GtkAdjustment *adjust = adjustment_->gtkobj();
  239.   if (toc == NULL) {
  240.     adjust->lower = 0.0;
  241.     adjust->upper = 1.0;
  242.     adjust->value = 0.0;
  243.     adjust->page_size = 0.0;
  244.   }
  245.   else {
  246.     adjust->lower = 0.0;
  247.     adjust->upper = toc->length().samples();
  248.     adjust->value = minSample_;
  249.     adjust->step_increment = len / 4;
  250.     if (adjust->step_increment == 0.0)
  251.       adjust->step_increment = 1.0;
  252.     adjust->page_increment = len / 1.1;
  253.     adjust->page_size = len;
  254.   }
  255.   adjustment_->changed();
  256.   
  257. }
  258. void SampleDisplay::getView(unsigned long *start, unsigned long *end)
  259. {
  260.   *start = minSample_;
  261.   *end = maxSample_;
  262. }
  263. int SampleDisplay::getSelection(unsigned long *start, unsigned long *end)
  264. {
  265.   if (selectionSet_) {
  266.     *start = selectionStartSample_;
  267.     *end = selectionEndSample_;
  268.     return 1;
  269.   }
  270.   
  271.   return 0;
  272. }
  273. int SampleDisplay::getMarker(unsigned long *sample)
  274. {
  275.   if (markerSet_) {
  276.     *sample = markerSample_;
  277.     return 1;
  278.   }
  279.   return 0;
  280. }
  281. void SampleDisplay::setSelectedTrackMarker(int trackNr, int indexNr)
  282. {
  283.   selectedTrack_ = trackNr;
  284.   selectedIndex_ = indexNr;
  285. }
  286. void SampleDisplay::setRegion(unsigned long start, unsigned long end)
  287. {
  288.   Toc *toc = tocEdit_->toc();
  289.   if (end <= start || end >= toc->length().samples()) {
  290.     regionSet_ = 0;
  291.   }
  292.   else {
  293.     regionStartSample_ = start;
  294.     regionEndSample_ = end;
  295.     regionSet_ = 1;
  296.   }
  297.   setView(minSample_, maxSample_);
  298. }
  299. int SampleDisplay::getRegion(unsigned long *start, unsigned long *end)
  300. {
  301.   if (regionSet_) {
  302.     *start = regionStartSample_;
  303.     *end = regionEndSample_;
  304.     return 1;
  305.   }
  306.   return 0;
  307. }
  308. void SampleDisplay::setCursor(int ctrl, unsigned long sample)
  309. {
  310.   if (ctrl == 0) {
  311.     cursorControlExtern_ = 0;
  312.   }
  313.   else {
  314.     cursorControlExtern_ = 1;
  315.     gint x = sample2pixel(sample);
  316.     if (x >= 0)
  317.       drawCursor(x);
  318.     else
  319.       undrawCursor();
  320.   }
  321. }
  322. void SampleDisplay::getColor(const char *colorName, Gdk_Color *color)
  323. {
  324.   if (!color->parse(colorName) || !get_colormap().alloc(*color)) {
  325.     message(-1, "Cannot allocate color "%s"", colorName);
  326.     *color = get_colormap().black();
  327.   }
  328. }
  329. void SampleDisplay::scrollTo()
  330. {
  331.   Toc *toc = tocEdit_->toc();
  332.   GtkAdjustment *adjust = adjustment_->gtkobj();
  333.   if (adjust->page_size == 0.0)
  334.     return;
  335.   minSample_ = (unsigned long)adjust->value;
  336.   maxSample_ = (unsigned long)(adjust->value + adjust->page_size) - 1;
  337.   if (maxSample_ >= toc->length().samples()) {
  338.     maxSample_ = toc->length().samples() - 1;
  339.     if (maxSample_ <= (unsigned long)(adjust->page_size - 1))
  340.       minSample_ = 0;
  341.     else 
  342.       minSample_ = maxSample_ - (unsigned long)(adjust->page_size - 1);
  343.   }
  344.   updateSamples();
  345.   redraw(0, 0, width_, height_, 0);
  346. }
  347. unsigned long SampleDisplay::pixel2sample(gint x)
  348. {
  349.   Toc *toc = tocEdit_->toc();
  350.   unsigned long sample;
  351.   if (toc->length().lba() == 0)
  352.     return 0;
  353.   assert(x >= sampleStartX_ && x <= sampleEndX_);
  354.   x -= sampleStartX_;
  355.   double res = maxSample_ - minSample_;
  356.   res /= sampleWidthX_ - 1;
  357.   sample = (unsigned long)(minSample_ + res * x + 0.5);
  358.   unsigned long round = 75 * 588; // 1 second
  359.   unsigned long rest;
  360.   if (res >=  2 * round) {
  361.     if ((rest = sample % round) != 0)
  362.       sample += round - rest;
  363.   }
  364.   else {
  365.     round = 588; // 1 block
  366.     if (res >= 2 * round) {
  367.       if ((rest = sample % round) != 0)
  368. sample += round - rest;
  369.     }
  370.   }
  371.   if (sample > maxSample_)
  372.     sample = maxSample_;
  373.   return sample;
  374. }
  375. gint SampleDisplay::sample2pixel(unsigned long sample)
  376. {
  377.   if (sample < minSample_ || sample > maxSample_)
  378.     return -1;
  379.   unsigned long len = maxSample_ - minSample_;
  380.   double val = sample - minSample_;
  381.   val *= sampleWidthX_ - 1;
  382.   val /= len;
  383.   return (gint)(sampleStartX_ + val + 0.5);
  384. }
  385. int SampleDisplay::handle_configure_event (GdkEventConfigure *event)
  386. {
  387.   if (drawGc_ == NULL) {
  388.     Gdk_Bitmap mask;
  389.     Gdk_Window window(get_window());
  390.     drawGc_ = new Gdk_GC(window);
  391.     getColor("darkslateblue", &sampleColor_);
  392.     getColor("red3", &middleLineColor_);
  393.     getColor("gold2", &cursorColor_);
  394.     getColor("red", &markerColor_);
  395.     getColor("#ffc0e0", &selectionBackgroundColor_);
  396.     timeTickFont_ = new Gdk_Font("fixed");
  397.     drawGc_->set_font(*timeTickFont_);
  398.     trackMarkerFont_ = timeTickFont_;
  399.     timeLineHeight_ = timeTickFont_->char_height('0') + 6;
  400.     trackLineHeight_ = timeTickFont_->char_height('0') + 10;
  401.     trackMarkerPixmap_ = new Gdk_Pixmap;
  402.     trackMarkerPixmap_->create_from_xpm_d(window, mask,
  403.   get_colormap().white(),
  404.   TRACK_MARKER_XPM_DATA);
  405.     indexMarkerPixmap_ = new Gdk_Pixmap;
  406.     indexMarkerPixmap_->create_from_xpm_d(window, mask,
  407.   get_colormap().white(),
  408.   INDEX_MARKER_XPM_DATA);
  409.     trackMarkerSelectedPixmap_ = new Gdk_Pixmap;
  410.     trackMarkerSelectedPixmap_->create_from_xpm_d(window, mask,
  411.   markerColor_,
  412.   TRACK_MARKER_XPM_DATA);
  413.     indexMarkerSelectedPixmap_ = new Gdk_Pixmap;
  414.     indexMarkerSelectedPixmap_->create_from_xpm_d(window, mask,
  415.   markerColor_,
  416.   INDEX_MARKER_XPM_DATA);
  417.     trackExtendPixmap_ = new Gdk_Pixmap;
  418.     trackExtendPixmap_->create_from_xpm_d(window, mask,
  419.   get_colormap().white(),
  420.   TRACK_EXTEND_XPM_DATA);
  421.     indexExtendPixmap_ = new Gdk_Pixmap;
  422.     indexExtendPixmap_->create_from_xpm_d(window, mask,
  423.   get_colormap().white(),
  424.   INDEX_EXTEND_XPM_DATA);
  425.     trackMarkerWidth_ = trackMarkerWidth();
  426.     trackManager_ = new TrackManager(TRACK_MARKER_XPM_WIDTH);
  427.   }
  428.   width_ = width();
  429.   height_ = height();
  430.   chanHeight_ = (height_ - timeLineHeight_ - trackLineHeight_ - 2) / 2;
  431.   lcenter_ = chanHeight_ / 2 + trackLineHeight_;
  432.   rcenter_ = lcenter_ + timeLineHeight_ + chanHeight_;
  433.   trackLineY_ = trackLineHeight_ - 1;
  434.   timeLineY_ = chanHeight_ + timeLineHeight_ + trackLineHeight_;
  435.   timeTickWidth_ = timeTickWidth();
  436.   sampleStartX_ = 10;
  437.   sampleEndX_ = width_ - 10;
  438.   sampleWidthX_ = sampleEndX_ - sampleStartX_ + 1;
  439.   
  440.   if (pixmap_ != NULL)
  441.     delete pixmap_;
  442.   pixmap_ = new Gdk_Pixmap(get_window(), width(), height(), -1);
  443.   //message(0, "handle_configure_event: %dn", width_);
  444.   updateSamples();
  445.   return TRUE;
  446. }
  447. int SampleDisplay::handle_expose_event (GdkEventExpose *event)
  448. {
  449.   redraw(event->area.x, event->area.y, event->area.width, event->area.height,
  450.  0);
  451.   return FALSE;
  452. }
  453. int SampleDisplay::handleButtonPressEvent(GdkEventButton *event)
  454. {
  455.   gint x = (gint)event->x;
  456.   gint y = (gint)event->y;
  457.   dragMode_ = DRAG_NONE;
  458.   if (cursorControlExtern_)
  459.     return TRUE;
  460.   if (event->button == 1 && x >= sampleStartX_ && x <= sampleEndX_) {
  461.     if (y > trackLineY_) {
  462.       dragMode_ = DRAG_SAMPLE_MARKER;
  463.       dragStart_ = dragEnd_ = x;
  464.     }
  465.     else {
  466.       if ((pickedTrackMarker_ = trackManager_->pick(x - sampleStartX_ + 4,
  467.     &dragStopMin_,
  468.     &dragStopMax_)) != NULL) {
  469. dragMode_ = DRAG_TRACK_MARKER;
  470. dragStart_ = dragEnd_ = x;
  471. dragLastX_ = -1;
  472. dragStopMin_ += sampleStartX_;
  473. dragStopMax_ += sampleStartX_;
  474.       }
  475.     }
  476.   }
  477.   return TRUE;
  478. }
  479. int SampleDisplay::handleButtonReleaseEvent(GdkEventButton *event)
  480. {
  481.   gint x = (gint)event->x;
  482.   if (cursorControlExtern_)
  483.     return TRUE;
  484.   if (x < sampleStartX_) {
  485.     x = sampleStartX_;
  486.   }
  487.   else if (x > sampleEndX_) {
  488.     x = sampleEndX_;
  489.   }
  490.   if (event->button == 1 && dragMode_ != DRAG_NONE) {
  491.     if (dragMode_ == DRAG_SAMPLE_MARKER) {
  492.       if (dragStart_ - x >= -5 && dragStart_ - x <= 5) {
  493. markerSet(pixel2sample(dragStart_));
  494.       }
  495.       else {
  496. selectionSet_ = 1;
  497. if (x > dragStart_) {
  498.   selectionStartSample_ = pixel2sample(dragStart_);
  499.   selectionEndSample_ = pixel2sample(x);
  500.   selectionStart_ = dragStart_;
  501.   selectionEnd_ = x;
  502. }
  503. else {
  504.   selectionEndSample_ = pixel2sample(dragStart_);
  505.   selectionStartSample_ = pixel2sample(x);
  506.   selectionEnd_ = dragStart_;
  507.   selectionStart_ = x;
  508. }
  509. selectionSet(selectionStartSample_, selectionEndSample_);
  510.       }
  511.     }
  512.     else if (dragMode_ == DRAG_TRACK_MARKER) {
  513.       if (dragStart_ - x >= -5 && dragStart_ - x <= 5) {
  514. trackManager_->select(pickedTrackMarker_);
  515. selectedTrack_ = pickedTrackMarker_->trackNr;
  516. selectedIndex_ = pickedTrackMarker_->indexNr;
  517. drawTrackLine();
  518. trackMarkSelected(pickedTrackMarker_->track, selectedTrack_,
  519.   selectedIndex_);
  520.       }
  521.       else {
  522. selectedTrack_ = pickedTrackMarker_->trackNr;
  523. selectedIndex_ = pickedTrackMarker_->indexNr;
  524. trackMarkMoved(pickedTrackMarker_->track, selectedTrack_,
  525.        selectedIndex_, pixel2sample(x));
  526.       }
  527.       pickedTrackMarker_ = NULL;
  528.     }
  529.     dragMode_ = DRAG_NONE;
  530.     drawCursor(x);
  531.     redraw(0, 0, width_, height_, 0);
  532.   }
  533.   return TRUE;
  534. }
  535. int SampleDisplay::handle_motion_notify_event (GdkEventMotion *event)
  536. {
  537.   gint x, y;
  538.   GdkModifierType state;
  539.   if (cursorControlExtern_)
  540.     return TRUE;
  541.   
  542.   if (event->is_hint)
  543.     gdk_window_get_pointer (event->window, &x, &y, &state);
  544.   else {
  545.     x = (gint)event->x;
  546.     y = (gint)event->y;
  547.     state = (GdkModifierType) event->state;
  548.   }
  549.   if (dragMode_ == DRAG_SAMPLE_MARKER) {
  550.     gint dw = 0;
  551.     gint dx;
  552.     if (x < sampleStartX_)
  553.       x = sampleStartX_;
  554.     else if (x > sampleEndX_)
  555.       x = sampleEndX_;
  556.     
  557.     if (selectionEnd_ > dragStart_) {
  558.       if (x < selectionEnd_) {
  559. redraw(x + 1, 0, selectionEnd_ - x, height_, 0x01);
  560. if (x < dragStart_) {
  561.   dw = dragStart_ - x + 1;
  562.   dx = x;
  563. }
  564.       }
  565.       else {
  566. dw = x - selectionEnd_;
  567. dx = selectionEnd_ + 1;
  568.       }
  569.     }
  570.     else if (selectionEnd_ < dragStart_) {
  571.       if (x > selectionEnd_) {
  572. redraw(selectionEnd_, 0, x - selectionEnd_, height_, 0x01);
  573. if (x > dragStart_) {
  574.   dw = x - dragStart_ + 1;
  575.   dx = dragStart_;
  576. }
  577.       }
  578.       else {
  579. dw = selectionEnd_ - x;
  580. dx = x;
  581.       }
  582.     }
  583.     if (dw != 0) {
  584.       drawGc_->set_foreground(cursorColor_);
  585.       drawGc_->set_function(GDK_XOR);
  586.       get_window().draw_rectangle(*drawGc_, TRUE, dx, 0, dw, height_ - 1);
  587.       drawGc_->set_function(GDK_COPY);
  588.     }      
  589.     selectionEnd_ = x;
  590.   }
  591.   else if (dragMode_ == DRAG_TRACK_MARKER) {
  592.     if (x < dragStopMin_)
  593.       x = dragStopMin_;
  594.     if (x > dragStopMax_)
  595.       x = dragStopMax_;
  596.     if (dragLastX_ > 0) {
  597.       drawTrackMarker(2, dragLastX_, 0, 0, 0, 0);
  598.     }
  599.     drawTrackMarker(1, x, pickedTrackMarker_->trackNr,
  600.     pickedTrackMarker_->indexNr, 0, 0);
  601.     dragLastX_ = x;
  602.     drawCursor(x);
  603.   }
  604.   else {
  605.     drawCursor(x);
  606.   }
  607.   
  608.   return TRUE;
  609. }
  610. int SampleDisplay::handleEnterEvent(GdkEventCrossing *event)
  611. {
  612.   if (cursorControlExtern_)
  613.     return TRUE;
  614.   drawCursor((gint)event->x);
  615.   return TRUE;
  616. }
  617. int SampleDisplay::handleLeaveEvent(GdkEventCrossing *event)
  618. {
  619.   if (cursorControlExtern_)
  620.     return TRUE;
  621.   undrawCursor();
  622.   return TRUE;
  623. }
  624. // drawMask: 0x01: do not draw cursor
  625. //           0x02: do not draw marker
  626. void SampleDisplay::redraw(gint x, gint y, gint width, gint height,
  627.    int drawMask)
  628. {
  629.   get_window().draw_pixmap(*drawGc_, *pixmap_, x, y, x, y, width, height);
  630.   if ((drawMask & 0x02) == 0)
  631.     drawMarker();
  632.   if ((drawMask & 0x01) == 0 && cursorDrawn_) {
  633.     cursorDrawn_ = 0;
  634.     drawCursor(cursorX_);
  635.   }
  636. }
  637. void SampleDisplay::drawMarker()
  638. {
  639.   if (markerSet_) {
  640.     drawGc_->set_foreground(markerColor_);
  641.     markerX_ = sample2pixel(markerSample_);
  642.     if (markerX_ >= 0) 
  643.       get_window().draw_line(*drawGc_, markerX_, trackLineY_,
  644.      markerX_, height_ - 1);
  645.   }
  646. }
  647. void SampleDisplay::setMarker(unsigned long sample)
  648. {
  649.   if (markerSet_)
  650.     redraw(markerX_, 0, 1, height_, 0x02);
  651.   markerSample_ = sample;
  652.   markerSet_ = 1;
  653.   drawMarker();
  654. }
  655. void SampleDisplay::clearMarker()
  656. {
  657.   if (markerSet_)
  658.     redraw(markerX_, 0, 1, height_, 0x02);
  659.   markerSet_ = 0;
  660. }
  661. void SampleDisplay::updateSamples()
  662. {
  663.   Toc *toc = tocEdit_->toc();
  664.   if (pixmap_ == NULL)
  665.     return;
  666.   gint halfHeight = chanHeight_ / 2;
  667.   drawGc_->set_foreground(get_colormap().white());
  668.   pixmap_->draw_rectangle(*drawGc_, TRUE, 0, 0, width_, height_);
  669.   
  670.   long res = (maxSample_ - minSample_ + 1)/sampleWidthX_;
  671.   long bres = res / tocEdit_->sampleManager()->blocking();
  672.   gint i;
  673.   double pos;
  674.   long j;
  675.   unsigned long s;
  676.   short lnegsum, lpossum, rnegsum, rpossum;
  677.   gint regionStart = -1;
  678.   gint regionEnd = -1;
  679.   int regionActive = 0;
  680.   if (regionSet_) {
  681.     if (regionStartSample_ <= maxSample_ &&
  682. regionEndSample_ >= minSample_) {
  683.       if (regionStartSample_ > minSample_)
  684. regionStart = sample2pixel(regionStartSample_);
  685.       else
  686. regionStart = sampleStartX_;
  687.       if (regionEndSample_ < maxSample_)
  688. regionEnd = sample2pixel(regionEndSample_);
  689.       else
  690. regionEnd = sampleEndX_;
  691.     }
  692.     if (regionStart >= 0 && regionEnd >= regionStart) {
  693.       drawGc_->set_foreground(selectionBackgroundColor_);
  694.       pixmap_->draw_rectangle(*drawGc_, TRUE,
  695.       regionStart, lcenter_ - halfHeight,
  696.       regionEnd - regionStart + 1, chanHeight_);
  697.       pixmap_->draw_rectangle(*drawGc_, TRUE,
  698.       regionStart, rcenter_ - halfHeight,
  699.       regionEnd - regionStart + 1, chanHeight_);
  700.     }
  701.   }
  702.   drawGc_->set_foreground(sampleColor_);
  703.   if (bres > 0) {
  704.     //message(0, "Draw 1");
  705.     for (s = minSample_, i = sampleStartX_;
  706.  s < maxSample_ && i <= sampleEndX_;
  707.  s += res, i++) {
  708.       lnegsum = lpossum = rnegsum = rpossum = 0;
  709.       if (regionStart != -1 && i >= regionStart && regionActive == 0) {
  710. regionActive = 1;
  711. drawGc_->set_foreground(markerColor_);
  712.       }
  713.       else if (regionActive == 1 && i > regionEnd) {
  714. regionActive = 2;
  715. drawGc_->set_foreground(sampleColor_);
  716.       }
  717.       tocEdit_->sampleManager()->getPeak(s, s + res, &lnegsum, &lpossum,
  718.  &rnegsum, &rpossum);
  719.       pos = double(lnegsum) * halfHeight;
  720.       pos /= SHRT_MAX;
  721.       //pos /= bres;
  722.       if (pos != 0)
  723. pixmap_->draw_line(*drawGc_, i, lcenter_, i, lcenter_ - (gint)pos);
  724.       
  725.       pos = double(lpossum) * halfHeight;
  726.       pos /= SHRT_MAX;
  727.       //pos /= bres;
  728.       if (pos != 0)
  729. pixmap_->draw_line(*drawGc_, i, lcenter_, i, lcenter_ - (gint)pos);
  730.       
  731.       pos = double(rnegsum) * halfHeight;
  732.       pos /= SHRT_MAX;
  733.       //pos /= bres;
  734.       if (pos != 0)
  735. pixmap_->draw_line(*drawGc_, i, rcenter_, i, rcenter_ - (gint)pos);
  736.       
  737.       pos = double(rpossum) * halfHeight;
  738.       pos /= SHRT_MAX;
  739.       //pos /= bres;
  740.       if (pos != 0)
  741. pixmap_->draw_line(*drawGc_, i, rcenter_, i, rcenter_ - (gint)pos);
  742.     }
  743.   }
  744.   else if (maxSample_ > 0 && res >= 1) {
  745.     //message(0, "Draw 2: %ld < %ld", res,
  746.     //        tocEdit_->sampleManager()->blocking());
  747.     TocReader reader(toc);
  748.     if (reader.openData() == 0) {
  749.       Sample *sampleBuf = new Sample[tocEdit_->sampleManager()->blocking()];
  750.       double dres = double(maxSample_ - minSample_ + 1)/double(sampleWidthX_);
  751.       double ds;
  752.       for (ds = minSample_, i = sampleStartX_;
  753.    ds < maxSample_ && i <= sampleEndX_;
  754.    ds += dres, i++) {
  755. lnegsum = lpossum = rnegsum = rpossum = 0;
  756. if (reader.seekSample((long)ds) == 0 &&
  757.     reader.readSamples(sampleBuf, res) == res) {
  758.   for (j = 0; j < res; j++) {
  759.     if (sampleBuf[j].left() < lnegsum)
  760.       lnegsum = sampleBuf[j].left();
  761.     if (sampleBuf[j].left() > lpossum)
  762.       lpossum = sampleBuf[j].left();
  763.     if (sampleBuf[j].right() < rnegsum)
  764.       rnegsum = sampleBuf[j].right();
  765.     if (sampleBuf[j].right() > rpossum)
  766.       rpossum = sampleBuf[j].right();
  767.   }
  768. }
  769. if (regionStart != -1 && i >= regionStart && regionActive == 0) {
  770.   regionActive = 1;
  771.   drawGc_->set_foreground(markerColor_);
  772. }
  773. else if (regionActive == 1 && i > regionEnd) {
  774.   regionActive = 2;
  775.   drawGc_->set_foreground(sampleColor_);
  776. }
  777. pos = double(lnegsum) * halfHeight;
  778. pos /= SHRT_MAX;
  779. //pos /= bres;
  780. if (pos != 0)
  781.   pixmap_->draw_line(*drawGc_, i, lcenter_, i, lcenter_ - (gint)pos);
  782.       
  783. pos = double(lpossum) * halfHeight;
  784. pos /= SHRT_MAX;
  785. //pos /= bres;
  786. if (pos != 0)
  787.   pixmap_->draw_line(*drawGc_, i, lcenter_, i, lcenter_ - (gint)pos);
  788. pos = double(rnegsum) * halfHeight;
  789. pos /= SHRT_MAX;
  790. //pos /= bres;
  791. if (pos != 0)
  792.   pixmap_->draw_line(*drawGc_, i, rcenter_, i, rcenter_ - (gint)pos);
  793. pos = double(rpossum) * halfHeight;
  794. pos /= SHRT_MAX;
  795. //pos /= bres;
  796. if (pos != 0)
  797.   pixmap_->draw_line(*drawGc_, i, rcenter_, i, rcenter_ - (gint)pos);
  798.       }
  799.       delete[] sampleBuf;
  800.       reader.closeData();
  801.     }
  802.   }
  803.   else if (toc != NULL && maxSample_ > minSample_ + 1) {
  804.     //message(0, "Draw 3");
  805.     TocReader reader(toc);
  806.     if (reader.openData() == 0) {
  807.       long len = maxSample_ - minSample_ + 1;
  808.       Sample *sampleBuf = new Sample[len];
  809.       double pres = double(sampleWidthX_ - 1) / double(len - 1);
  810.       double di;
  811.       gint pos1;
  812.       gint lastPosLeft, lastPosRight;
  813.       //printf("Drawing exact, res=%ld pres=%g %ld-%ldn", res, pres, minSample_, maxSample_);
  814.       if (reader.seekSample(minSample_) == 0 &&
  815.   reader.readSamples(sampleBuf, len) == len) {
  816. //printf("Drawing exact1n");
  817. for (j = 1, di = sampleStartX_ + pres;
  818.      j < len && di < sampleEndX_ + 1; j++, di += pres) {
  819.   if (regionStart != -1 && regionActive == 0 &&
  820.       minSample_ + j - 1 >= regionStartSample_ &&
  821.       minSample_ + j <= regionEndSample_) {
  822.     regionActive = 1;
  823.     drawGc_->set_foreground(markerColor_);
  824.   }
  825.   else if (regionActive == 1 && minSample_ + j > regionEndSample_) {
  826.     regionActive = 2;
  827.     drawGc_->set_foreground(sampleColor_);
  828.   }
  829.   pos = sampleBuf[j - 1].left() * halfHeight;
  830.   pos /= SHRT_MAX;
  831.   pos1 = sampleBuf[j].left() * halfHeight;
  832.   pos1 /= SHRT_MAX;
  833.   lastPosLeft = pos1;
  834.   if (pos != 0 || pos1 != 0)
  835.     pixmap_->draw_line(*drawGc_, long(di - pres), lcenter_ - (gint)pos,
  836.        long(di), lcenter_ - pos1);
  837.   pos = sampleBuf[j - 1].right() * halfHeight;
  838.   pos /= SHRT_MAX;
  839.   pos1 = sampleBuf[j].right() * halfHeight;
  840.   pos1 /= SHRT_MAX;
  841.   lastPosRight = pos1;
  842.   if (pos != 0 || pos1 != 0)
  843.     pixmap_->draw_line(*drawGc_, long(di - pres), rcenter_ - (gint)pos,
  844.        long(di), rcenter_ - pos1);
  845. }
  846. if (0 && (gint)di < sampleEndX_) {
  847.   pos = sampleBuf[len -1].left() * halfHeight;
  848.   pos /= SHRT_MAX;
  849.   if (pos != 0 || lastPosLeft != 0)
  850.     pixmap_->draw_line(*drawGc_, long(di), lcenter_ - lastPosLeft, 
  851.        sampleEndX_, lcenter_ - (gint)pos);
  852.   
  853.   pos = sampleBuf[len - 1].right() * halfHeight;
  854.   pos /= SHRT_MAX;
  855.   if (pos != 0 || lastPosRight != 0)
  856.     pixmap_->draw_line(*drawGc_, long(di), rcenter_ - lastPosRight,
  857.        sampleEndX_, rcenter_ - (gint)pos);
  858. }
  859.       }
  860.       delete[] sampleBuf;
  861.     }
  862.   }
  863.   drawGc_->set_foreground(middleLineColor_);
  864.   pixmap_->draw_line(*drawGc_, sampleStartX_, lcenter_, sampleEndX_, lcenter_);
  865.   pixmap_->draw_line(*drawGc_, sampleStartX_, rcenter_, sampleEndX_, rcenter_);
  866.   drawGc_->set_foreground(get_colormap().black());
  867.   pixmap_->draw_line(*drawGc_, sampleStartX_ - 1, lcenter_ - halfHeight,
  868.      sampleEndX_ + 1, lcenter_ - halfHeight);
  869.   pixmap_->draw_line(*drawGc_, sampleStartX_ - 1, lcenter_ + halfHeight,
  870.      sampleEndX_ + 1, lcenter_ + halfHeight);
  871.   pixmap_->draw_line(*drawGc_, sampleStartX_ - 1, lcenter_ - halfHeight,
  872. sampleStartX_ - 1, lcenter_ + halfHeight);
  873.   pixmap_->draw_line(*drawGc_, sampleEndX_ + 1, lcenter_ - halfHeight,
  874.      sampleEndX_ + 1, lcenter_ + halfHeight);
  875.   pixmap_->draw_line(*drawGc_, sampleStartX_ - 1, rcenter_ - halfHeight,
  876.      sampleEndX_ + 1, rcenter_ - halfHeight);
  877.   pixmap_->draw_line(*drawGc_, sampleStartX_ - 1, rcenter_ + halfHeight,
  878.      sampleEndX_ + 1, rcenter_ + halfHeight);
  879.   pixmap_->draw_line(*drawGc_, sampleStartX_ - 1, rcenter_ + halfHeight,
  880.      sampleStartX_ - 1, rcenter_ - halfHeight);
  881.   pixmap_->draw_line(*drawGc_, sampleEndX_ + 1, rcenter_ + halfHeight,
  882.      sampleEndX_ + 1, rcenter_ - halfHeight);
  883.   drawTimeLine();
  884.   trackManager_->update(toc, minSample_, maxSample_, sampleWidthX_);
  885.   if (selectedTrack_ > 0) {
  886.     trackManager_->select(selectedTrack_, selectedIndex_);
  887.   }
  888.   drawTrackLine();
  889. }
  890. void SampleDisplay::drawCursor(gint x)
  891. {
  892.   if (pixmap_ == NULL)
  893.     return;
  894.   if (x < sampleStartX_ || x > sampleEndX_)
  895.     return;
  896.   if (cursorDrawn_ && cursorX_ != x) {
  897.     redraw(cursorX_, 0, 1, height_, 0x01);
  898.   }
  899.   
  900.   if (!cursorDrawn_ || cursorX_ != x) {
  901.     drawGc_->set_foreground(cursorColor_);
  902.     get_window().draw_line(*drawGc_, x, trackLineY_, x, height_ - 1);
  903.   }
  904.   
  905.   cursorDrawn_ = 1;
  906.   cursorX_ = x;
  907.   if (cursorControlExtern_ == 0)
  908.     cursorMoved(pixel2sample(x));
  909. }
  910. void SampleDisplay::undrawCursor()
  911. {
  912.   if (cursorDrawn_) {
  913.     redraw(cursorX_, 0, 1, height_, 0x01);
  914.     cursorDrawn_ = 0;
  915.   }
  916. }
  917. void SampleDisplay::drawTimeTick(gint x, gint y, unsigned long sample)
  918. {
  919.   char buf[50];
  920.   if (pixmap_ == NULL)
  921.     return;
  922.   unsigned long min = sample / (60 * 44100);
  923.   sample %= 60 * 44100;
  924.   unsigned long sec = sample / 44100;
  925.   sample %= 44100;
  926.   unsigned long frame = sample / 588;
  927.   sample %= 588;
  928.   sprintf(buf, "%lu:%02lu:%02lu.%03lu", min, sec, frame, sample);
  929.   drawGc_->set_foreground(get_colormap().black());
  930.   pixmap_->draw_line(*drawGc_, x, y - timeLineHeight_, x, y);
  931.   pixmap_->draw_string(*timeTickFont_, *drawGc_, x + 3, y - 3, buf);
  932. }
  933. gint SampleDisplay::timeTickWidth()
  934. {
  935.   return timeTickFont_->string_width("000:00:00.000") + 3;
  936. }
  937. void SampleDisplay::drawTimeLine()
  938. {
  939.   Toc *toc = tocEdit_->toc();
  940.   if (toc->length().lba() == 0)
  941.     return;
  942.   gint sep = timeTickWidth_ + timeTickSep_;
  943.   int maxNofTicks = (sampleWidthX_ + timeTickSep_) / sep;
  944.   gint x;
  945.   unsigned long len = maxSample_ - minSample_ + 1;
  946.   unsigned long dt;
  947.   unsigned long dtx;
  948.   unsigned long startSample;
  949.   unsigned long s;
  950.   if ((s = len / (60 * 44100)) > 1) {
  951.     dt = 60 * 44100;
  952.   }
  953.   else if ((s = len / 44100) > 1) {
  954.     dt = 44100;
  955.   }
  956.   else if ((s = len / 588) > 1) {
  957.     dt = 588;
  958.   }
  959.   else {
  960.     dt = 1;
  961.     s = len;
  962.   }
  963.   if (s > maxNofTicks) {
  964.     dtx = s / maxNofTicks;
  965.     if (s % maxNofTicks != 0)
  966.       dtx++;
  967.     dtx *= dt;
  968.   }
  969.   else {
  970.     dtx = dt;
  971.   }
  972.   if (dt > 1) {
  973.     if (minSample_ % dt == 0) {
  974.       startSample = minSample_;
  975.     }
  976.     else {
  977.       startSample = minSample_ / dt;
  978.       startSample = startSample * dt + dt;
  979.     }
  980.   }
  981.   else {
  982.     startSample = minSample_;
  983.   }
  984.   for (s = startSample; s < maxSample_; s += dtx) {
  985.     x = sample2pixel(s);
  986.     if (x + timeTickWidth_ <= sampleEndX_) 
  987.       drawTimeTick(x, timeLineY_, s);
  988.   }
  989. }
  990. gint SampleDisplay::trackMarkerWidth()
  991. {
  992.   return trackMarkerFont_->string_width("00.00") + TRACK_MARKER_XPM_WIDTH + 2;
  993. }
  994. // Draws track marker.
  995. // mode: 0: draw on 'pixmap_'
  996. //       1: draw on window
  997. //       2: redraw region at given position
  998. void SampleDisplay::drawTrackMarker(int mode, gint x, int trackNr,
  999.     int indexNr, int selected, int extend)
  1000. {
  1001.   if (mode < 2) {
  1002.     char buf[20];
  1003.     sprintf(buf, "%d.%d", trackNr, indexNr);
  1004.     Gdk_Pixmap *marker;
  1005.     if (extend) {
  1006.       marker = indexNr == 1 ? trackExtendPixmap_ : indexExtendPixmap_;
  1007.     }
  1008.     else {
  1009.       if (selected)
  1010. marker = indexNr == 1 ? trackMarkerSelectedPixmap_ :
  1011.                         indexMarkerSelectedPixmap_;
  1012.       else
  1013. marker = indexNr == 1 ? trackMarkerPixmap_ : indexMarkerPixmap_;
  1014.     }
  1015.     Gdk_Drawable dr(get_window());
  1016.     if (mode == 0)
  1017.       dr = *pixmap_;
  1018.     if (mode == 0) {
  1019.       if (selected)
  1020. drawGc_->set_foreground(markerColor_);
  1021.       else
  1022. drawGc_->set_foreground(get_colormap().white());
  1023.       dr.draw_rectangle(*drawGc_, TRUE,  x-4, trackLineY_ - trackLineHeight_,
  1024. trackMarkerWidth_, trackLineHeight_);
  1025.     }
  1026.     drawGc_->set_foreground(get_colormap().black());
  1027.     dr.draw_pixmap(*drawGc_, *marker, 0, 0,
  1028.    x - 4, trackLineY_ - TRACK_MARKER_XPM_HEIGHT,
  1029.    TRACK_MARKER_XPM_WIDTH, TRACK_MARKER_XPM_HEIGHT);
  1030.     dr.draw_string(*trackMarkerFont_, *drawGc_, 
  1031.     x + TRACK_MARKER_XPM_WIDTH / 2 + 2, trackLineY_ - 1, buf);
  1032.   }
  1033.   else {
  1034.     redraw(x - 4, trackLineY_ - trackLineHeight_, trackMarkerWidth_,
  1035.    trackLineHeight_, 0x03);
  1036.   }
  1037. }
  1038. void SampleDisplay::drawTrackLine()
  1039. {
  1040.   const TrackManager::Entry *run;
  1041.   const TrackManager::Entry *selected = NULL;
  1042.   for (run = trackManager_->first(); run != NULL;
  1043.        run = trackManager_->next()) {
  1044.     if (run->selected != 0 && run->extend == 0) {
  1045.       selected = run;
  1046.     }
  1047.     else if (run->indexNr != 1 || run->extend != 0) {
  1048.       drawTrackMarker(0, sampleStartX_ + run->xpos, run->trackNr, run->indexNr,
  1049.       0, run->extend);
  1050.     }
  1051.   }
  1052.   for (run = trackManager_->first(); run != NULL;
  1053.        run = trackManager_->next()) {
  1054.     if (run->indexNr == 1 && run->selected == 0 && run->extend == 0) {
  1055.       drawTrackMarker(0, sampleStartX_ + run->xpos, run->trackNr, run->indexNr,
  1056.       0, run->extend);
  1057.     }
  1058.   }
  1059.   if (selected != NULL)
  1060.     drawTrackMarker(0, sampleStartX_ + selected->xpos, selected->trackNr,
  1061.     selected->indexNr, 1, 0);
  1062. }
  1063. void SampleDisplay::updateTrackMarks()
  1064. {
  1065.   Toc *toc = tocEdit_->toc();
  1066.   drawGc_->set_foreground(get_colormap().white());
  1067.   pixmap_->draw_rectangle(*drawGc_, TRUE,
  1068.   sampleStartX_ - 4, trackLineY_ - trackLineHeight_,
  1069.   width_ - sampleStartX_, trackLineHeight_);
  1070.   trackManager_->update(toc, minSample_, maxSample_, sampleWidthX_);
  1071.   if (selectedTrack_ > 0) {
  1072.     trackManager_->select(selectedTrack_, selectedIndex_);
  1073.   }
  1074.   drawTrackLine();
  1075.   
  1076.   redraw(0, 0, width_, height_, 0x03);
  1077. }