Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorWu-Hsi Li <wuhsi@media.mit.edu>2014-03-02 07:30:35 (GMT)
committer Wu-Hsi Li <wuhsi@media.mit.edu>2014-03-02 07:30:35 (GMT)
commitd01c66e757b835f5feba0f995694f0f9fc5cb630 (patch)
tree946a26f8a446adf8d091a74e5ecd9bd5ea1c9fb4
init commit
-rw-r--r--Brick.py194
-rw-r--r--BrickBrowser.py657
-rw-r--r--BricksArea.py969
-rw-r--r--Canvas.py1502
-rw-r--r--CsoundAPI.py614
-rw-r--r--CsoundXOAgent.py140
-rw-r--r--MPScore.py780
-rw-r--r--Musicpainter.py920
-rw-r--r--MusicpainterActivity.py86
-rw-r--r--ToolbarArea.py549
-rw-r--r--checkVersion.py49
-rw-r--r--codes.py78
-rw-r--r--setup.py3
13 files changed, 6541 insertions, 0 deletions
diff --git a/Brick.py b/Brick.py
new file mode 100644
index 0000000..5d6a1b7
--- /dev/null
+++ b/Brick.py
@@ -0,0 +1,194 @@
+import random
+from copy import deepcopy
+
+class Brick:
+ def minusone(self, n1, n2):
+ array = [[-1 for i in range(n2)] for j in range(n1)]
+ return array
+
+ def zeros(self, n1, n2):
+ array = [[0 for i in range(n2)] for j in range(n1)]
+ return array
+
+ def zeros3(self, n1, n2, n3):
+ array = [[[0 for i in range(n3)] for j in range(n2)] for k in range(n1)]
+ return array
+
+ def __init__(self, w, h, platform, mp):
+
+ self.platform = platform
+# self.top = self.minusone(w, h)
+
+ self.map = self.zeros3(8, w, h)
+ self.cut = self.zeros3(8, w, h)
+
+ self.filename = ""
+ self.ngrid_h = w
+ self.ngrid_v = h
+
+ self.title = ""
+ self.description = ""
+ self.note = ""
+ self.sval = 0.5
+ self.scale_mode = 0
+ self.key_shift = 0
+ self.author = ""
+ self.brick_type = 0 # 0: normal(pitch) 1: scale 2: rhythm
+
+ self.is_blank = 1
+# self.width = self.ngrid_h/2 * self.gridw # width for empty score = 1/2 full score width
+# self.swid = self.ngrid_h/2
+ self.swid = 27
+ self.width = self.swid # width for empty score = 1/2 full score width
+
+ self.cx, self.cy = 0, 0
+
+ self.main = mp
+
+ def clear_self(self):
+ self.is_blank = 1
+ self.filename = ""
+ self.swid = 27
+ self.width = self.swid
+ self.scale_mode = 0
+ self.key_shift = 0
+
+ def copy_brick(self, brick):
+ if brick.is_blank == 1:
+ self.clear_self()
+ return
+ self.is_blank = 0
+ self.filename = brick.filename
+ self.brick_type = brick.brick_type
+ self.swid = brick.swid
+ self.width = brick.width
+ self.scale_mode = brick.scale_mode
+ self.key_shift = brick.key_shift
+ self.sval = brick.sval
+ self.map = deepcopy(brick.map)
+ self.cut = deepcopy(brick.cut)
+ self.cx = brick.cx
+ self.cy = brick.cy
+
+ def clear_score(self):
+ w = self.ngrid_h
+ h = self.ngrid_v
+# self.top = self.minusone(w, h)
+ self.map = self.zeros3(8, w, h)
+ self.cut = self.zeros3(8, w, h)
+
+ def dump_score(self, map, cut, mode, shift):
+ # update width
+ x0, x1 = -1, -1
+ y0, y1 = -1, -1
+ self.clear_score()
+ for k in range(self.ngrid_h):
+ for i in range(8):
+ for j in range(self.ngrid_v):
+ if map[i][k][j] != 0:
+ if x0 == -1:
+ x0 = k
+ x1 = k
+ if y0 == -1 or j < y0:
+ y0 = j
+ if y1 == -1 or j > y1:
+ y1 = j
+ self.map[i][k-x0][j] = map[i][k][j]
+ self.cut[i][k-x0][j] = cut[i][k][j]
+ self.swid = x1-x0+1
+ self.width = self.swid
+ self.scale_mode = mode
+ self.key_shift = shift
+ (self.cx, self.cy) = ((x1-x0)/2, (y1+y0)/2)
+ self.is_blank = 0
+
+ def read_score(self, filename, score):
+ if filename == self.filename:
+ return
+ (map, cut, a, self.scale_mode, self.key_shift, type, author, self.title, self.description, self.note) = score.read_score("myscore/"+filename)
+ self.filename = filename
+ self.brick_type = type
+ self.author = author
+ self.dump_score(map, cut, self.scale_mode, self.key_shift)
+ self.sval = a
+
+ def filename_generator(self):
+ if self.brick_type == 0:
+ name = self.main.username + "_0_" + str(self.scale_mode) + "_br" + str(random.randint(0, 9999999)) + ".mpb"
+ else:
+ name = self.main.username + "_2_0_br" + str(random.randint(0, 9999999)) + ".mpb"
+ print "filename generated: " + name
+ return name
+
+ def write_score(self, score): # generate a filename and save
+ self.filename = self.filename_generator()
+ score.write_score("myscore/" + self.filename, self.map, self.cut, self.main.toolbar.sval, self.scale_mode, self.key_shift, self.brick_type)
+
+ def is_pitch_brick(self):
+ for k in range(self.ngrid_h):
+ for j in range(self.ngrid_v):
+ for i in range(7):
+ if self.map[i][k][j] != 0:
+ return True
+ return False
+
+ def is_rhythm_brick(self):
+ for k in range(self.ngrid_h):
+ for j in range(self.ngrid_v):
+ if self.map[7][k][j] != 0:
+ return True
+ return False
+
+ def play_music(self):
+# print "play brick..."
+ csound = self.main.csound
+ if csound.status != 1:
+ return
+ if self.is_blank == 1:
+ return
+ score = self.main.score
+ score.startSessionTime = score.currentTime
+# if self.play_state == -1:
+# self.main.canvas.highlight_grid(True)
+ if self.brick_type == 1 or self.brick_type == -1 or self.filename.endswith("mps") or score.play_continue != -1:
+ score.play_continue = -1
+ score.time_continue = 99999999
+ csound.sendClearLines()
+# self.startSessionTime = self.currentTime
+
+ div = 0.1 * pow(6.25, 1-self.sval)
+# print "%.2f %.2f" % (self.sval, div)
+ (events, st, et) = score.score2events(self.map, self.cut, div)
+# self.backup_events = events
+ score.ecnt = len(events) #length
+ limit = 144
+ if st != -1:
+ if score.ecnt > limit:
+ t = limit
+ score.play_continue = limit
+ score.time_continue = events[limit][1] + score.currentTime - 0.5
+ score.backup_events = events
+ else:
+ t = score.ecnt
+ score.play_continue = -1
+ score.time_continue = 99999999
+ for i in range(t):
+ if events[i][0] == 8:
+ estr = "i" + str(events[i][0]) + " " + str(events[i][1]) + " " + str(events[i][2]) + " " + str(events[i][3]) + " " + str(events[i][4])
+ elif events[i][0] == 7:
+ n = score.note2str(score.map_scale2(events[i][4],self.scale_mode,self.key_shift-12))
+ estr = "i" + str(events[i][0]) + " " + str(events[i][1]) + " " + str(events[i][2]) + " " + str(events[i][3]) + " " + str(n)
+ else:
+ n = score.note2str(score.map_scale2(events[i][4],self.scale_mode,self.key_shift))
+ estr = "i" + str(events[i][0]) + " " + str(events[i][1]) + " " + str(events[i][2]) + " " + str(events[i][3]) + " " + str(n)
+ csound.sendLinevt(estr)
+# self.sendEvents()
+# self.play_time = 0
+# self.play_state = -1
+# self.score_start_time = st
+# self.score_end_time = et
+# else:
+# self.play_state = -2
+
+# if _showCSoundMsg:
+# print "Playing CSound Music..."
diff --git a/BrickBrowser.py b/BrickBrowser.py
new file mode 100644
index 0000000..4d74b87
--- /dev/null
+++ b/BrickBrowser.py
@@ -0,0 +1,657 @@
+import gtk
+import pygtk
+import random
+
+class BrickBrowser(gtk.DrawingArea):
+
+ def __init__(self, wid, hei, platform, mp):
+
+ self.main = mp
+ self.platform = platform
+ self.width, self.height = wid, hei
+
+ self.init_data()
+ self.init_graphics()
+ gtk.DrawingArea.__init__(self)
+
+ self.set_size_request(self.width, self.height)
+
+ self.connect("expose_event", self.expose_event)
+ self.connect("configure_event", self.configure_event)
+ self.connect("leave_notify_event", self.leave_notify_event)
+ self.connect("motion_notify_event", self.motion_notify_event)
+ self.connect("button_press_event", self.button_press_event)
+ self.connect("button_release_event", self.button_release_event)
+
+ self.set_events(gtk.gdk.EXPOSURE_MASK
+ | gtk.gdk.LEAVE_NOTIFY_MASK
+ | gtk.gdk.BUTTON_PRESS_MASK
+ | gtk.gdk.BUTTON_RELEASE_MASK
+ | gtk.gdk.POINTER_MOTION_MASK
+ | gtk.gdk.POINTER_MOTION_HINT_MASK)
+
+ def init_data(self):
+ self.flag = 0 # 0 off 1 on
+ self.fix_button = 0
+ self.brick_highlight = -1
+ self.drag_brick = -1
+ self.select_brick = -1
+ self.drag_state = 0
+ self.list = []
+ self.listf = []
+ self.list_p = 0
+ self.page_cnt = [0 for i in range(1000)]
+
+ self.all_brick_list = []
+ self.active_brick_list = []
+
+ self.button_highlight = -1
+ self.btns = ["Back","Stop","Prev","Next","Refresh","Load"]
+
+ self.bx1 = [0 for i in range(self.main.score.tesize)]
+ self.bx2 = [0 for i in range(self.main.score.tesize)]
+ self.by = [0 for i in range(self.main.score.tesize)]
+
+ self.no_update = False
+ self.update_pending = 0
+ self.ready = 0
+
+ self.loadmode = False
+
+ #self.create_all_list()
+ #self.lucky_pick()
+ #self.load_temp_list()
+
+ def init_graphics(self):
+ self.cx = (int)(0.09 * self.width)
+ self.cy = 10
+ self.btn_h = 42
+
+ self.gridw = self.main.bricksarea.gridw
+ self.gridh = self.main.bricksarea.gridh
+ self.ngrid_v = self.main.bricksarea.ngrid_v
+ self.ngrid_h = self.main.bricksarea.ngrid_h
+
+ self.ahei = self.main.bricksarea.chei * 4
+ self.thei = self.ahei + 4*3 + 2*2
+ self.height = self.cy * 2 + self.thei
+
+ def configure_event(self, widget, event):
+ x, y, width, height = widget.get_allocation()
+ self.pixmap = gtk.gdk.Pixmap(widget.window, width, height)
+ return True
+
+ def leave_notify_event(self, widget, event):
+ return
+
+ def button_press_event(self, widget, event):
+ self.fix_button = self.fix_button + 1
+ if self.fix_button != 1:
+ return
+ if event.button == 1:
+ t = self.is_on_brick(event.x, event.y)
+# print "Back 0 %d" % t
+ if t != -1:
+ if self.drag_state == 1 and self.loadmode:
+ if self.drag_brick == t:
+ self.drag_state = 2
+ else:
+ self.draw_1_score(self.drag_brick, t)
+ self.drag_brick = t
+ self.filename_label.set_text(self.main.score.temp_bricks[t].filename)
+ self.author_label.set_text(self.main.score.temp_bricks[t].author)
+ if self.main.score.temp_bricks[t].filename.endswith("mps"):
+ name = "Composition"
+ elif self.main.score.temp_bricks[t].brick_type == 2:
+ name = "Rhythm Brick"
+ else:
+ name = "Melody Brick"
+ self.type_label.set_text(name)
+ self.scale_label.set_text(self.main.score.scale_list[self.main.score.temp_bricks[t].scale_mode])
+ self.title_label.set_text(self.main.score.temp_bricks[t].title)
+ self.desc_label.set_text(self.main.score.temp_bricks[t].description)
+ self.note_label.set_text(self.main.score.temp_bricks[t].note)
+ else:
+ self.drag_brick = t
+ self.drag_state = 1
+ else:
+ t = self.is_on_button(event.x, event.y)
+ if t != 1 and t != 5 and self.drag_state == 1:
+ self.drag_state = 0
+ self.draw_1_score(self.drag_brick, -1)
+
+# print "Back 1 %d" % t
+ if t == 0: # back
+ self.main.browser_layout.remove(self.main.bricksarea)
+ if self.platform != "sugar-xo":
+ self.main.window.remove(self.main.browser_layout)
+ self.main.layout.put(self.main.bricksarea, 0, self.main.toolbararea_height + self.main.canvas_height)
+ if self.platform == "sugar-xo":
+ self.main.window.set_canvas(self.main.layout)
+ else:
+ self.main.window.add(self.main.layout)
+ self.main.window.show_all()
+ self.fix_button = 0
+ self.flag = 0
+ elif t == 1: # stop
+ self.main.score.stop_music(self.main.csound)
+ elif t == 2: # prev
+ if self.list_p > 0:
+ self.list_p = self.list_p - 1
+ self.load_temp_list_1page()
+ self.draw_scores()
+ elif t == 3: # next
+ if self.page_cnt[self.list_p] < len(self.list):
+ self.list_p = self.list_p + 1
+# self.list_p = self.list_p + self.main.score.tesize
+ self.load_temp_list_1page()
+ self.draw_scores()
+ elif t == 4: # refresh
+ self.update_all_list()
+ elif t == 5: # load
+ if self.drag_state == 1:
+ self.main.browser_layout.remove(self.main.bricksarea)
+ if self.platform != "sugar-xo":
+ self.main.window.remove(self.main.browser_layout)
+ self.main.layout.put(self.main.bricksarea, 0, self.main.toolbararea_height + self.main.canvas_height)
+ if self.platform == "sugar-xo":
+ self.main.window.set_canvas(self.main.layout)
+ else:
+ self.main.window.add(self.main.layout)
+ self.main.window.show_all()
+ self.fix_button = 0
+ self.flag = 0
+ self.drag_state = 0
+ self.main.canvas.canvas_load_score(self.main.score.temp_bricks[self.drag_brick].filename)
+ return
+
+ def button_release_event(self, widget, event):
+ self.fix_button = 0
+ if self.drag_state == 2 and self.loadmode:
+ t = self.is_on_brick(event.x, event.y)
+ if self.drag_brick == t:
+ self.main.score.temp_bricks[t].play_music()
+ self.drag_state = 1
+ else:
+ self.draw_1_score(self.drag_brick, t)
+ self.brick_highlight = t
+ self.drag_state = 0
+ elif self.drag_state == 1:
+ t = self.is_on_brick(event.x, event.y)
+ if not self.loadmode:
+ if self.drag_brick == t:
+ self.main.score.temp_bricks[t].play_music()
+ else:
+ self.draw_1_score(self.drag_brick, t)
+ self.brick_highlight = t
+ self.drag_state = 0 # drag to
+ if not self.loadmode:
+ bricka = self.main.bricksarea
+ score = self.main.score
+ t = bricka.is_on_brickarea(event.x, event.y - self.main.canvas_height)
+ if t:
+ grp = -1
+ brick = score.temp_bricks[self.drag_brick]
+ if brick.author == self.main.username:
+ if brick.brick_type == 0:
+ grp = 1
+ elif brick.brick_type == 2:
+ grp = 2
+ else:
+ if brick.brick_type == 0:
+ grp = 4
+ elif brick.brick_type == 2:
+ grp = 5
+ if grp != -1 and bricka.add_brick(grp, brick):
+ if grp !=bricka.active_group:
+ bricka.change_active_group(grp)
+ else:
+ bricka.bricks_cnt = bricka.bricks_cnt + 1
+ bricka.draw_scores()
+ self.active_brick_list.append(brick.filename)
+ self.draw_1_score(-1, self.drag_brick)
+
+ def motion_notify_event(self, widget, event):
+ if event.is_hint:
+ x, y, state = event.window.get_pointer()
+ else:
+ x, y = event.x, event.y
+ state = event.state
+ t = self.is_on_brick(event.x, event.y)
+ if self.drag_state == 0 and t != self.brick_highlight and (self.brick_highlight != -1 or t != -1):
+ if t == -1:
+ self.filename_label.set_text("")
+ self.author_label.set_text("")
+ self.type_label.set_text("")
+ self.scale_label.set_text("")
+ self.title_label.set_text("")
+ self.desc_label.set_text("")
+ self.note_label.set_text("")
+ else:
+ self.filename_label.set_text(self.main.score.temp_bricks[t].filename)
+ self.author_label.set_text(self.main.score.temp_bricks[t].author)
+ if self.main.score.temp_bricks[t].filename.endswith("mps"):
+ name = "Composition"
+ elif self.main.score.temp_bricks[t].brick_type == 2:
+ name = "Rhythm Brick"
+ else:
+ name = "Melody Brick"
+ self.type_label.set_text(name)
+ self.scale_label.set_text(self.main.score.scale_list[self.main.score.temp_bricks[t].scale_mode])
+ self.title_label.set_text(self.main.score.temp_bricks[t].title)
+ self.desc_label.set_text(self.main.score.temp_bricks[t].description)
+ self.note_label.set_text(self.main.score.temp_bricks[t].note)
+ self.draw_1_score(self.brick_highlight, t)
+ self.brick_highlight = t
+ t = self.is_on_button(event.x, event.y)
+ if self.drag_state == 0 and t != self.button_highlight:
+ self.button_highlight = t
+ self.draw_buttons()
+
+ def expose_event(self, widget, event):
+ print "expose_event"
+ self.widget = widget
+ self.ready = 1
+ cr = self.pixmap.cairo_create()
+
+ # set a clip region for the expose event
+ x , y, width, height = event.area
+ cr.rectangle(x, y, width, height)
+ cr.clip()
+
+ self.draw(cr)
+ # draw_drawable?
+ if self.update_pending == 1:
+ if self.main.type_box.get_active_text() == "Compositions":
+ self.draw_buttons()
+ self.draw_scores()
+ self.update_pending = 0
+ widget.window.draw_drawable(widget.get_style().fg_gc[gtk.STATE_NORMAL], self.pixmap, x, y, x, y, width, height)
+ return False
+
+ def draw_curvy_rectangle(self, cr, x0, y0, x1, y1, r, highlight):
+ if highlight == 0:
+ cr.set_source_rgb(0.80,0.80,0.80)
+ else:
+ cr.set_source_rgb(0.92,0.92,0.92)
+ cr.move_to(x0, y0 + r)
+ cr.curve_to(x0, y0, x0, y0, x0+r, y0)
+ cr.line_to(x1-r, y0)
+ cr.curve_to(x1, y0, x1, y0, x1, y0+r)
+ cr.line_to(x1, y1-r)
+ cr.curve_to(x1, y1, x1, y1, x1-r, y1)
+ cr.line_to(x0+r, y1)
+ cr.curve_to(x0, y1, x0, y1, x0, y1-r)
+ cr.close_path()
+ cr.fill_preserve()
+ cr.set_line_width(1)
+ cr.set_source_rgb(0.98, 0.98, 0.98)
+ cr.stroke()
+
+ def is_on_brick(self, x, y):
+ if y < self.cy - 2 or y > self.cy + self.ahei + 12:
+ return -1
+ if x < self.cx or x > self.width-20:
+ return -1
+ bricka = self.main.bricksarea
+ for i in range(self.main.score.temp_bricks_cnt):
+ if self.list_p == 0 and i >= self.page_cnt[self.list_p]:
+ return -1
+ elif self.list_p > 0 and i >= (self.page_cnt[self.list_p] - self.page_cnt[self.list_p - 1]):
+ return -1
+# print "%d %d %d %d %d" % (x, y, self.bx1[i], self.bx2[i], self.by[i])
+ if y >= self.by[i] and y < (self.by[i] + bricka.chei) and x >= self.bx1[i] and x < self.bx2[i]:
+ return i
+ return -1
+
+ def draw_1_score(self, t1, t2):
+ cr = self.pixmap.cairo_create()
+ widget = self.widget
+ bricka = self.main.bricksarea
+ ty = bricka.cy
+ if t1 != -1:
+ bricka.cy = self.by[t1]
+ bricka.draw_mini_score(cr, self.bx1[t1]-self.cx, self.main.score.temp_bricks[t1], self.listf[t1+self.list_p])
+ if t2 != -1:
+ bricka.cy = self.by[t2]
+ bricka.draw_mini_score(cr, self.bx1[t2]-self.cx, self.main.score.temp_bricks[t2], 1)
+ bricka.cy = ty
+ widget.window.draw_drawable(widget.get_style().fg_gc[gtk.STATE_NORMAL], self.pixmap, self.cx, 0, self.cx, 0, self.width, self.height)
+
+ def is_on_button(self, x, y):
+ if x < 12 or x >= self.cx - 12:
+ return -1
+ for i in range(len(self.btns)):
+ if i == len(self.btns)-1 and self.main.type_box.get_active_text() != "Compositions":
+ continue;
+ if y >= self.cy + i*self.btn_h and y < self.cy + i*self.btn_h + self.btn_h - 8:
+ return i
+ return -1
+
+ def draw_scores(self):
+ cr = self.pixmap.cairo_create()
+ widget = self.widget
+ score = self.main.score
+ bricka = self.main.bricksarea
+ self.draw_curvy_rectangle(cr, self.cx-2, self.cy-5, self.width-20+2, self.cy + self.ahei+16, 8, 0)
+
+ x = 5
+ row = 0
+ ty = bricka.cy
+ bricka.cy = self.cy + 2
+ if self.list_p == 0:
+ self.page_cnt[self.list_p] = score.temp_bricks_cnt
+ else:
+ self.page_cnt[self.list_p] = self.page_cnt[self.list_p-1] + score.temp_bricks_cnt
+ for i in range(score.temp_bricks_cnt):
+ brick = score.temp_bricks[i]
+ if x + brick.width * self.gridw > self.width-20-self.cx:
+ row = row + 1
+ bricka.cy = bricka.cy + bricka.chei + 4
+ x = 5
+ if row >= 4:
+ if self.list_p == 0:
+ self.page_cnt[self.list_p] = i + 1
+ else:
+ self.page_cnt[self.list_p] = i + 1 + self.page_cnt[self.list_p - 1]
+ break
+ if self.list_p == 0:
+ bricka.draw_mini_score(cr, x, brick, self.listf[i])
+ else:
+ bricka.draw_mini_score(cr, x, brick, self.listf[i+self.page_cnt[self.list_p-1]])
+ self.bx1[i] = self.cx + x
+ self.bx2[i] = self.cx + x + brick.width * self.gridw
+ self.by[i] = bricka.cy
+ x = x + brick.width * self.gridw + bricka.bdiv + 2
+ bricka.cy = ty
+ widget.window.draw_drawable(widget.get_style().fg_gc[gtk.STATE_NORMAL], self.pixmap, self.cx, 0, self.cx, 0, self.width, self.height)
+
+ def draw(self, cr):
+ cr.set_source_rgb(0.84, 0.84, 1)
+ cr.rectangle(0, 0, self.width, self.height)
+ cr.fill()
+
+ self.draw_buttons()
+ self.draw_scores()
+
+ def draw_buttons(self):
+ cr = self.pixmap.cairo_create()
+
+ cr.set_source_rgb(0.84, 0.84, 1)
+ cr.rectangle(0, 0, self.cx, self.height)
+ cr.fill()
+
+ widget = self.widget
+ cr.set_font_size(18)
+ for i in range(len(self.btns)):
+ if i == len(self.btns)-1 and self.main.type_box.get_active_text() != "Compositions":
+ continue;
+ (x0, y0) = (12, self.cy + i * self.btn_h)
+ (x1, y1) = (self.cx-12, self.cy + i * self.btn_h + self.btn_h - 8)
+ self.draw_curvy_rectangle(cr, x0, y0, x1, y1, 4, (self.button_highlight == i))
+ xb, yb, wid, hei = cr.text_extents(self.btns[i])[:4]
+ cr.set_source_rgb(0.4, 0.4, 0.4)
+ cr.move_to( (x0+x1)/2 - wid/2 - xb, (y0+y1)/2 - hei/2 - yb)
+ cr.show_text(self.btns[i])
+ widget.window.draw_drawable(widget.get_style().fg_gc[gtk.STATE_NORMAL], self.pixmap, 0, 0, 0, 0, self.cx-3, self.height)
+
+ def get_file_info(self, filename):
+ try:
+ n = filename.split("_")
+ l = len(n)
+ if filename.endswith("mps"):
+ type = -1
+ else:
+ type = (int)(n[l-3])
+ scale = (int)(n[l-2])
+ if l == 4:
+ author = n[0]
+ else:
+ author = ""
+ for i in range(l-3):
+ author = author + n[i]
+ if i != l-4:
+ author = author + "_"
+ except:
+ return ["invalid_filename", 0, 0]
+ else:
+ return [author, type, scale]
+
+ def update_author_list(self):
+ score = self.main.score
+ size1 = len(score.local_brick_list)
+ size2 = len(score.srv_brick_list)
+ self.main.model1.append([self.main.username])
+ for i in range(size1):
+ [author, type, scale] = self.get_file_info(score.local_brick_list[i])
+ if author == "invalid_filename":
+ continue;
+ flag = 0
+ for j in range(len(self.main.model1)):
+ if self.main.model1[j][0] == author:
+ flag = 1
+ break
+ if flag == 0:
+ self.main.model1.append([author])
+ for i in range(size2):
+ [author, type, scale] = self.get_file_info(score.srv_brick_list[i])
+ if author == "invalid_filename":
+ continue;
+ flag = 0
+ for j in range(len(self.main.model1)):
+ if self.main.model1[j][0] == author:
+ flag = 1
+ break
+ if flag == 0:
+ self.main.model1.append([author])
+
+ def combo_changed(self, widget, entry = None):
+ self.load_temp_list()
+ self.brick_highlight = -1
+ self.drag_brick = -1
+ self.drag_state = 0
+ self.loadmode = (self.main.type_box.get_active_text() == "Compositions")
+# if not self.loadmode:
+# self.drag_state = 0
+ if self.ready == 0:
+ self.update_pending = 1
+ return
+ self.draw_buttons()
+ self.draw_scores()
+
+ def filter(self, filename):
+ [author, type, scale] = self.get_file_info(filename)
+ if author == "invalid_filename":
+ return False
+
+ af = self.main.author_box.get_active_text()
+ if af != "All Authors":
+ if author != af:
+ return False
+
+ at = self.main.type_box.get_active_text()
+ if at == "Compositions" and type != -1:
+ return False
+ elif at == "All Bricks" and type == -1:
+ return False
+ elif at == "Melody Bricks" and type != 0:
+ return False
+ elif at == "Rhythm Bricks" and type != 2:
+ return False
+
+ a = self.main.scale_box.get_active()
+ if a == 0:
+ return True
+ elif a-1 != scale:
+ return False
+ return True
+
+ def writeline_cb(self, line):
+ self.stream.writelines(line + "\n")
+
+ def makesure_file_on_local(self, filename):
+ try:
+ file = open("myscore/" + filename)
+ except IOError:
+ if self.main.ftp_status == 1:
+ try:
+ self.stream = open("myscore/" + filename, 'w')
+ msg = self.main.ftp.retrlines("RETR " + filename, self.writeline_cb)
+ print "ftp::RETR " + filename + "...." + msg
+ self.stream.close()
+ except IOError:
+ return False
+ else:
+ return True
+ else:
+ return True
+
+ def update_all_list(self):
+ score = self.main.score
+ try:
+ score.srv_brick_list = self.main.ftp.nlst("*.mp*")
+ except:
+ score.srv_brick_list = []
+ self.main.ftp_status = 0
+ score.create_local_brick_list()
+
+ size1 = len(score.local_brick_list)
+ size2 = len(score.srv_brick_list)
+
+ for i in range(size1):
+ try:
+ self.all_brick_list.index(score.local_brick_list[i])
+ except ValueError:
+ self.all_brick_list.append(score.local_brick_list[i])
+
+ for i in range(size2):
+ try:
+ self.all_brick_list.index(score.srv_brick_list[i])
+ except ValueError:
+ self.all_brick_list.append(score.srv_brick_list[i])
+ self.combo_changed(self.widget)
+
+ def create_all_list(self):
+ if not self.main.update_author:
+ self.update_author_list()
+ self.main.update_author = True
+ score = self.main.score
+
+ self.active_brick_list = []
+ for i in range(score.work_bricks_cnt):
+ self.active_brick_list.append(score.work_bricks[i].filename)
+ for i in range(score.mymelody_bricks_cnt):
+ self.active_brick_list.append(score.mymelody_bricks[i].filename)
+ for i in range(score.myrhythm_bricks_cnt):
+ self.active_brick_list.append(score.myrhythm_bricks[i].filename)
+ for i in range(score.cmelody_bricks_cnt):
+ self.active_brick_list.append(score.cmelody_bricks[i].filename)
+ for i in range(score.crhythm_bricks_cnt):
+ self.active_brick_list.append(score.crhythm_bricks[i].filename)
+
+ self.all_brick_list = []
+ size1 = len(score.local_brick_list)
+ size2 = len(score.srv_brick_list)
+ print str(size1) + " files on local, " + str(size2) + " files on server"
+ self.list = []
+ for i in range(size1):
+ self.all_brick_list.append(score.local_brick_list[i])
+
+ for i in range(size2):
+ flag = 0
+ for j in range(len(self.all_brick_list)):
+ if self.all_brick_list[j] == score.srv_brick_list[i]:
+ flag = 1
+ break
+ if flag == 0:
+ self.all_brick_list.append(score.srv_brick_list[i])
+
+ t = len(self.all_brick_list)
+ for i in range(t * 10):
+ a = random.randint(0, t-1)
+ b = random.randint(0, t-1)
+ f = self.all_brick_list[a]
+ self.all_brick_list[a] = self.all_brick_list[b]
+ self.all_brick_list[b] = f
+
+ def change_status(self, name, new_state):
+ try:
+ id = self.list.index(name)
+ except ValueError:
+ return
+ else:
+ self.listf[id] = new_state
+
+ def create_list(self):
+ size = len(self.all_brick_list)
+ self.list = []
+ self.listf = []
+ for i in range(size):
+ if self.filter(self.all_brick_list[i]):
+ self.list.append(self.all_brick_list[i])
+ try:
+ id = self.active_brick_list.index(self.all_brick_list[i])
+ except ValueError:
+ self.listf.append(0) # not in list
+ else:
+ self.listf.append(1) # in active list
+
+ def lucky_pick(self): # automatically generate collected brick list
+ score = self.main.score
+ size = len(self.all_brick_list)
+ cnt = 0
+ while score.cmelody_bricks_cnt < 5:
+ cnt = cnt + 1
+ if cnt > 200:
+ break
+ a = random.randint(0, size-1)
+ name = self.all_brick_list[a]
+ [author, type, scale] = self.get_file_info(name)
+ if author == "invalid_filename" or author == self.main.username or type != 0:
+ continue
+ try:
+ id = self.active_brick_list.index(name)
+ except ValueError:
+ self.makesure_file_on_local(name)
+ self.active_brick_list.append(name)
+ score.cmelody_bricks[score.cmelody_bricks_cnt].read_score(name, score)
+ score.cmelody_bricks_cnt = score.cmelody_bricks_cnt + 1
+ cnt = 0
+ while score.crhythm_bricks_cnt < 5:
+ cnt = cnt + 1
+ if cnt > 200:
+ break
+ a = random.randint(0, size-1)
+ name = self.all_brick_list[a]
+ [author, type, scale] = self.get_file_info(name)
+ if author == "invalid_filename" or author == self.main.username or type != 2:
+ continue
+ try:
+ id = self.active_brick_list.index(name)
+ except ValueError:
+ self.makesure_file_on_local(name)
+ self.active_brick_list.append(name)
+ score.crhythm_bricks[score.crhythm_bricks_cnt].read_score(name, score)
+ score.crhythm_bricks_cnt = score.crhythm_bricks_cnt + 1
+
+ def load_temp_list_1page(self):
+ size = len(self.list)
+ score = self.main.score
+ score.temp_bricks_cnt = 0
+ if self.list_p == 0:
+ t = size
+ t2 = 0
+ else:
+ t = size - self.page_cnt[self.list_p-1]
+ t2 = self.page_cnt[self.list_p-1]
+ for i in range(t):
+ self.makesure_file_on_local(self.list[t2+i])
+ score.temp_bricks[i].read_score(self.list[t2+i], score)
+ score.temp_bricks_cnt = score.temp_bricks_cnt + 1
+ if i == score.tesize - 1:
+ break
+
+ def load_temp_list(self):
+ self.create_list()
+ self.list_p = 0
+ self.load_temp_list_1page()
diff --git a/BricksArea.py b/BricksArea.py
new file mode 100644
index 0000000..0dc86b8
--- /dev/null
+++ b/BricksArea.py
@@ -0,0 +1,969 @@
+import gtk
+
+from copy import deepcopy
+
+class BricksArea(gtk.DrawingArea):
+
+ def __init__(self, wid, hei, platform, mp):
+
+ self.main = mp
+ self.platform = platform
+ self.width, self.height = wid, hei
+
+ self.init_data()
+ self.init_graphics()
+ gtk.DrawingArea.__init__(self)
+
+ self.set_size_request(self.width, self.height)
+
+ self.connect("expose_event", self.expose_event)
+ self.connect("configure_event", self.configure_event)
+ self.connect("enter_notify_event", self.enter_notify_event)
+ self.connect("leave_notify_event", self.leave_notify_event)
+ self.connect("motion_notify_event", self.motion_notify_event)
+ self.connect("button_press_event", self.button_press_event)
+ self.connect("button_release_event", self.button_release_event)
+
+ self.set_events(gtk.gdk.EXPOSURE_MASK
+ | gtk.gdk.LEAVE_NOTIFY_MASK
+ | gtk.gdk.ENTER_NOTIFY_MASK
+ | gtk.gdk.BUTTON_PRESS_MASK
+ | gtk.gdk.BUTTON_RELEASE_MASK
+ | gtk.gdk.POINTER_MOTION_MASK
+ | gtk.gdk.POINTER_MOTION_HINT_MASK)
+
+ def init_data(self):
+ self.ngrid_h = 64
+ self.ngrid_v = 18
+
+ self.fix_button = 0
+
+ self.brick_added = False
+ self.scroll_width = -1 # to be set
+ self.scroll_x = 0
+ self.bricks_total_width = -1 # to be set
+ self.scroll_state = 0
+ self.drag_state = 0
+ self.bricks_cnt = self.main.score.work_bricks_cnt
+ #print "bricks_cnt = %d" % self.bricks_cnt
+
+ self.scroll_highlight = -1 # 0 left 1 main 2 right
+ self.brick_highlight = -1
+ self.label_highlight = -1
+
+ self.button_highlight = -1
+ self.btns = ["Save", "Explore"]
+
+ self.to_canvas = 0
+
+ self.drag_brick = -1
+
+ self.active_group = 0
+ self.group_list = ["Working Area","My Melody","My Rhythm","Scale","Collected Melody", "Collected Rhythm", "Trash Can"]
+ self.gx0 = [-1 for i in range(7)] # to be set
+ self.gx1 = [-1 for i in range(7)] # to be set
+
+ def init_graphics(self):
+
+ self.ready = 0
+
+ self.cx = (int)(0.09 * self.width)
+ self.cy = 40
+ self.btn_h = 42
+
+ self.gridw = 1+ (int)(0.4+1.0*self.width/64/4)
+ v1 = (int)(1.0*(self.height - 2 * self.cy) / self.ngrid_v)
+ v2 = (int)((0.25 * (self.main.canvas.height - 108) - 6) / self.ngrid_v)
+
+ if v2 < v1:
+ self.gridh = v2
+ else:
+ self.gridh = v1
+
+# print "(" + str(self.gridw) +"," + str(self.gridh) + ")"
+
+ self.chei = self.ngrid_v*self.gridh + 4
+ self.cwid = self.ngrid_h*self.gridw + 12
+ self.bdiv = 10
+
+ self.sx0, self.sx1 = self.cx+2, self.width - 20
+ self.max_sx = 0 # to be set
+
+ self.blue = gtk.gdk.Color(0,1280,57600)
+ self.green = gtk.gdk.Color(9728,38912,4608)
+ self.red = gtk.gdk.Color(65535,15000,15000)
+ self.yellow = gtk.gdk.Color(64000, 65000, 500)
+ self.purple = gtk.gdk.color_parse('purple')
+ self.orange = gtk.gdk.color_parse('orange')
+ self.lblue = gtk.gdk.Color(0, 65535, 65535)
+ self.grass = gtk.gdk.Color(41728, 63744, 512)
+
+ self.color_list = [self.red,self.orange,self.yellow,self.grass,self.green,self.lblue,self.blue,self.purple]
+
+ def configure_event(self, widget, event):
+ x, y, width, height = widget.get_allocation()
+ self.pixmap = gtk.gdk.Pixmap(widget.window, width, height)
+ self.left_margin_pixmap = gtk.gdk.Pixmap(widget.window, self.cx, height)
+ return True
+
+ def enter_notify_event(self, widget, event):
+# print "bricksarea.enter"
+ self.main.cursor_area = 3
+ self.main.grab_focus()
+
+ def leave_notify_event(self, widget, event):
+# print "bricksarea.leave"
+ if self.main.cursor_area == 3:
+ self.main.cursor_area = 0
+ if self.scroll_highlight != -1 or self.brick_highlight != -1:
+ self.scroll_highlight = -1
+ self.brick_highlight = -1
+ self.draw_scores()
+ if self.label_highlight != -1:
+ self.label_highlight = -1
+ cr = self.pixmap.cairo_create()
+ widget = self.widget
+ self.draw_labels(cr, 1)
+ widget.window.draw_drawable(widget.get_style().fg_gc[gtk.STATE_NORMAL], self.pixmap, self.cx, 0, self.cx, 0, self.sx1-self.sx0, self.height)
+ return
+
+ def button_press_event(self, widget, event):
+ self.fix_button = self.fix_button + 1
+ if self.fix_button != 1:
+ return
+ if event.button == 1:
+ t = self.is_scrolling(event.x, event.y)
+ if t == 1: # click right on the scrollbar
+ self.scroll_state = 1
+ self.start_drag_x = event.x
+ elif t == 2 or t == 4: # left
+ if t == 4:
+ self.scroll_x = self.scroll_x - self.scroll_width/8
+ else:
+ self.scroll_x = self.scroll_x - self.scroll_width/4
+ if self.scroll_x < 0:
+ self.scroll_x = 0
+ self.draw_scores()
+ elif t == 3 or t == 5: # right
+ if t == 5:
+ self.scroll_x = self.scroll_x + self.scroll_width/8
+ else:
+ self.scroll_x = self.scroll_x + self.scroll_width/4
+ if self.scroll_x >= self.max_sx:
+ self.scroll_x = self.max_sx - 1
+ self.draw_scores()
+ else:
+ t = self.is_on_brick(event.x, event.y)
+ if t == self.bricks_cnt:
+ if self.bricks_cnt != 20: # add a brick, only for working_area
+ if self.active_group == 0: # add a brick
+ self.bricks_cnt = self.bricks_cnt + 1
+ self.main.score.work_bricks_cnt = self.bricks_cnt
+ self.brick_highlight = self.bricks_cnt
+ self.update_scroll(-1, 1)
+ self.draw_scores()
+ elif self.active_group == 6: #clear bricks
+ for i in range(self.bricks_cnt):
+ self.main.score.bricks[i].clear_self()
+ self.bricks_cnt = 0
+ self.main.score.trash_bricks_cnt = 0
+ self.brick_highlight = 0
+ self.draw_scores()
+ elif t != -1: # click on a brick
+ if self.main.score.bricks[t].is_blank != 1:
+ self.drag_brick = t
+ score = self.main.score
+ if score.select_state == 1:
+ score.de_selection()
+ self.main.canvas.draw_deselection()
+ self.drag_state = 1
+ self.to_canvas = 0 # pending on the cursor is dragged into the canvas area
+ else: # blank brick can only be thrown to trash can
+ self.drag_brick = t
+ score = self.main.score
+ if score.select_state == 1:
+ score.de_selection()
+ self.main.canvas.draw_deselection()
+ self.drag_state = 2
+
+ else:
+ t = self.is_on_label(event.x, event.y)
+ if t != -1 and t != self.active_group:
+ self.active_group = t
+ score = self.main.score
+ if t == 0:
+ score.bricks = score.work_bricks
+ self.bricks_cnt = score.work_bricks_cnt
+ elif t == 1:
+ score.bricks = score.mymelody_bricks
+ self.bricks_cnt = score.mymelody_bricks_cnt
+ elif t == 2:
+ score.bricks = score.myrhythm_bricks
+ self.bricks_cnt = score.myrhythm_bricks_cnt
+ elif t == 3:
+ self.main.score.bricks = score.scale_bricks
+ self.bricks_cnt = score.scale_bricks_cnt
+ elif t == 4:
+ self.main.score.bricks = score.cmelody_bricks
+ self.bricks_cnt = score.cmelody_bricks_cnt
+ elif t == 5:
+ self.main.score.bricks = score.crhythm_bricks
+ self.bricks_cnt = score.crhythm_bricks_cnt
+ elif t == 6:
+ self.main.score.bricks = score.trash_bricks
+ self.bricks_cnt = score.trash_bricks_cnt
+ self.label_highlight = -1
+ cr = self.pixmap.cairo_create()
+ widget = self.widget
+ self.draw_labels(cr, 1)
+ widget.window.draw_drawable(widget.get_style().fg_gc[gtk.STATE_NORMAL], self.pixmap, self.cx, 0, self.cx, 0, self.sx1-self.sx0, self.height)
+ self.draw_scores()
+ else:
+ t = self.is_on_button(event.x, event.y)
+ if t == 0: # Save
+ flag = self.main.score.save_working_brick
+ self.main.score.save_working_brick = True
+ self.main.score.save_profile(self.main.username)
+ self.main.score.save_working_brick = flag
+ #browser = self.main.browser
+ #if browser.flag == 0:
+ #self.change_into_browser()
+ #self.fix_button = 0
+ #self.main.author_box.set_active(1)
+ #self.main.type_box.set_active(1)
+ #self.main.scale_box.set_active(0)
+ #browser.flag = 2
+ #elif browser.flag == 2:
+ #self.change_back()
+ #self.fix_button = 0
+ #else:
+ #self.main.author_box.set_active(1)
+ #self.main.type_box.set_active(1)
+ #self.main.scale_box.set_active(0)
+ #browser.flag = 2
+ elif t == 1: # Explore
+ browser = self.main.browser # 0 browser off 1 explore all brick 2 explore my brick
+ if browser.flag == 0: # 3 explore all composition 4 explore my composition
+ self.change_into_browser()
+ self.fix_button = 0
+ self.main.author_box.set_active(0)
+ self.main.type_box.set_active(1)
+ self.main.scale_box.set_active(0)
+ browser.flag = 1
+ elif browser.flag == 1:
+ self.change_back()
+ self.fix_button = 0
+ else:
+ self.main.author_box.set_active(0)
+ self.main.type_box.set_active(1)
+ self.main.scale_box.set_active(0)
+ browser.flag = 1
+
+ def change_into_browser(self):
+ browser = self.main.browser
+ window = self.main.window
+
+ if self.platform != "sugar-xo":
+ window.remove(self.main.layout)
+ self.main.layout.remove(self)
+ self.main.browser_layout.put(self, 0, self.main.toolbararea_height + self.main.canvas_height)
+ if self.platform == "sugar-xo":
+ window.set_canvas(self.main.browser_layout)
+ self.main.browser_layout.modify_bg(gtk.STATE_NORMAL, gtk.gdk.Color(55040, 55040, 65535))
+ else:
+ window.add(self.main.browser_layout)
+ window.show_all()
+
+ def change_back(self):
+ browser = self.main.browser
+ window = self.main.window
+ if self.platform != "sugar-xo":
+ window.remove(self.main.browser_layout)
+ self.main.browser_layout.remove(self)
+ self.main.layout.put(self, 0, self.main.toolbararea_height + self.main.canvas_height)
+ if self.platform == "sugar-xo":
+ window.set_canvas(self.main.layout)
+ else:
+ window.add(self.main.layout)
+ window.show_all()
+ browser.flag = 0
+
+ def change_active_group(self, grp):
+ self.active_group = grp
+ score = self.main.score
+
+ if grp == 0:
+ score.bricks = score.work_bricks
+ self.bricks_cnt = score.work_bricks_cnt
+ elif grp == 1:
+ score.bricks = score.mymelody_bricks
+ self.bricks_cnt = score.mymelody_bricks_cnt
+ elif grp == 2:
+ score.bricks = score.myrhythm_bricks
+ self.bricks_cnt = score.myrhythm_bricks_cnt
+ elif grp == 4:
+ score.bricks = score.cmelody_bricks
+ self.bricks_cnt = score.cmelody_bricks_cnt
+ elif grp == 5:
+ score.bricks = score.crhythm_bricks
+ self.bricks_cnt = score.crhythm_bricks_cnt
+
+ cr = self.pixmap.cairo_create()
+ widget = self.widget
+ self.draw_labels(cr, 1)
+ widget.window.draw_drawable(widget.get_style().fg_gc[gtk.STATE_NORMAL], self.pixmap, self.cx, 0, self.cx, 0, self.sx1-self.sx0, self.height)
+ self.draw_scores()
+
+ def delete_dragged_brick(self):
+ a = self.active_group
+ d = self.drag_brick
+ c = self.bricks_cnt
+ score = self.main.score
+ for i in range(c-d-1):
+ score.bricks[d+i].copy_brick(score.bricks[d+i+1])
+ score.bricks[c-1].clear_self()
+ self.bricks_cnt = self.bricks_cnt - 1
+ if a == 0:
+ score.work_bricks_cnt = score.work_bricks_cnt - 1
+ elif a == 1:
+ score.mymelody_bricks_cnt = score.mymelody_bricks_cnt - 1
+ elif a == 2:
+ score.myrhythm_bricks_cnt = score.myrhythm_bricks_cnt - 1
+ elif a == 4:
+ score.cmelody_bricks_cnt = score.cmelody_bricks_cnt - 1
+ elif a == 5:
+ score.crhythm_bricks_cnt = score.crhythm_bricks_cnt - 1
+ elif a == 5:
+ score.trash_bricks_cnt = score.trash_bricks_cnt - 1
+
+ def check_same(self, bricks, cnt, brick):
+ if brick.filename == "":
+ return False
+ for i in range(cnt):
+ if bricks[i].filename == brick.filename:
+ return True
+ return False
+
+ def add_brick(self, g, brick):
+ score = self.main.score
+ if g == 0:
+ if score.work_bricks_cnt == score.wsize or self.check_same(score.work_bricks, score.work_bricks_cnt, brick):
+ return False
+ score.work_bricks[score.work_bricks_cnt].copy_brick(brick)
+# score.work_bricks[score.work_bricks_cnt].filename = ""
+ score.work_bricks_cnt = score.work_bricks_cnt + 1
+ self.brick_added = True
+ elif g == 1:
+ if score.mymelody_bricks_cnt == score.csize or self.check_same(score.mymelody_bricks, score.mymelody_bricks_cnt, brick):
+ return False
+# if not brick.is_pitch_brick():
+# return False
+ t = score.mymelody_bricks_cnt
+ score.mymelody_bricks[t].copy_brick(brick)
+ score.mymelody_bricks[t].brick_type = 0
+# if score.mymelody_bricks[t].filename == "":
+# score.mymelody_bricks[t].write_score(score)
+# score.check_if_server_has_file(score.mymelody_bricks[t].filename)
+ score.mymelody_bricks_cnt = score.mymelody_bricks_cnt + 1
+ self.brick_added = True
+ elif g == 2:
+ if score.myrhythm_bricks_cnt == score.csize or self.check_same(score.myrhythm_bricks, score.myrhythm_bricks_cnt, brick):
+ return False
+# if not brick.is_rhythm_brick():
+# return False
+ t = score.myrhythm_bricks_cnt
+ score.myrhythm_bricks[t].copy_brick(brick)
+ score.myrhythm_bricks[t].brick_type = 2
+# if score.myrhythm_bricks[t].filename == "":
+# score.myrhythm_bricks[t].write_score(score)
+# score.check_if_server_has_file(score.myrhythm_bricks[t].filename)
+ score.myrhythm_bricks_cnt = score.myrhythm_bricks_cnt + 1
+ self.brick_added = True
+ elif g == 4:
+ if score.cmelody_bricks_cnt == score.csize or self.check_same(score.cmelody_bricks, score.cmelody_bricks_cnt, brick):
+ return False
+ score.cmelody_bricks[score.cmelody_bricks_cnt].copy_brick(brick)
+# score.cmelody_bricks[score.cmelody_bricks_cnt].brick_type = 0
+ score.cmelody_bricks_cnt = score.cmelody_bricks_cnt + 1
+ elif g == 5:
+ if score.crhythm_bricks_cnt == score.csize or self.check_same(score.crhythm_bricks, score.crhythm_bricks_cnt, brick):
+ return False
+ score.crhythm_bricks[score.crhythm_bricks_cnt].copy_brick(brick)
+# score.crhythm_bricks[score.crhythm_bricks_cnt].brick_type = 2
+ score.crhythm_bricks_cnt = score.crhythm_bricks_cnt + 1
+ elif g == 6:
+ if score.trash_bricks_cnt == score.tsize:
+ for i in range(score.trash_bricks_cnt-1):
+ score.trash_bricks[i].copy_brick(score.trash_bricks[i+1])
+ score.trash_bricks[score.trash_bricks_cnt-1].copy_brick(brick)
+ else:
+ score.trash_bricks[score.trash_bricks_cnt].copy_brick(brick)
+ score.trash_bricks_cnt = score.trash_bricks_cnt + 1
+ self.main.browser.active_brick_list.remove(brick.filename)
+ self.main.browser.change_status(brick.filename, 0)
+ else:
+ return False
+ return True
+
+ def button_release_event(self, widget, event):
+# print "bricksarea.mouse_btn_release (%d,%d)" % (event.x, event.y)
+ self.fix_button = 0
+ if self.drag_state == 1:
+ if self.main.score.bricks[self.drag_brick].brick_type == 1:
+ if self.main.browser.flag == 0:
+ gx, gy = self.main.canvas.within_score(event.x, event.y + self.main.canvas_height)
+ if gx != -1 and gy != -1:
+ self.main.score.scale_mode = self.drag_brick
+ self.main.canvas.draw_canvas_highlight(0)
+ self.draw_scores()
+ elif self.main.score.bricks[self.drag_brick].brick_type == 0 or self.main.score.bricks[self.drag_brick].brick_type == 2:
+ t = self.is_on_label(event.x, event.y)
+ a = self.active_group
+ if a != t and (a == 0 and (t == 1 or t == 2) or t == 6 and a != 3 or a == 6 and t >= 0 and t <= 2):
+ if self.add_brick(t, self.main.score.bricks[self.drag_brick]):
+ if a == 6:
+ name = self.main.score.bricks[self.drag_brick].filename
+ self.main.browser.active_brick_list.append(name)
+ self.main.browser.change_status(name, 1)
+ self.delete_dragged_brick()
+ cr = self.pixmap.cairo_create()
+ widget = self.widget
+ self.draw_labels(cr, 1)
+ widget.window.draw_drawable(widget.get_style().fg_gc[gtk.STATE_NORMAL], self.pixmap, self.cx, 0, self.cx, 0, self.sx1-self.sx0, self.height)
+ self.draw_scores()
+ self.drag_state = 0
+ if self.drag_state == 2 and self.is_on_label(event.x, event.y) == 6: # blank brick can only be thrown way
+ self.delete_dragged_brick()
+ self.draw_scores()
+ self.drag_state = 0
+ if self.scroll_state == 1:
+ self.scroll_state = 0
+ t = self.is_on_brick(event.x, event.y)
+ if self.drag_brick != -1 and self.drag_brick == t and self.bricks_cnt > t: # and event.type == gtk.gdk._2BUTTON_PRESS
+ self.main.score.bricks[t].play_music()
+ return
+
+ def motion_notify_event(self, widget, event):
+ if self.ready == 0:
+ return
+ if event.is_hint:
+ x, y, state = event.window.get_pointer()
+ else:
+ x, y = event.x, event.y
+ state = event.state
+
+ if self.scroll_state == 1:
+ tsx = self.scroll_x + (event.x - self.start_drag_x)
+ if tsx < 0:
+ tsx = 0
+ elif tsx >= self.max_sx:
+ tsx = self.max_sx
+ if tsx != self.scroll_x:
+ self.scroll_x = tsx
+ self.start_drag_x = event.x
+ self.draw_scores()
+ elif self.drag_state == 1:
+ if self.main.browser.flag == 0:
+ if self.to_canvas == 0: # check if the brick has been dragged into the canvas
+ gx, gy = self.main.canvas.within_score(event.x, event.y + self.main.canvas_height)
+ if gx != -1 and gy != -1: # yes it is
+ self.to_canvas = 1
+ score = self.main.score
+ t = self.drag_brick
+ if score.bricks[t].brick_type != 1:
+ self.main.toolbar.toolsel = 1
+ self.main.toolbar.update()
+ if score.bricks[t].brick_type == 0 or score.bricks[t].brick_type == 2:
+ score.drag = deepcopy(score.bricks[t].map)
+ score.dcut = deepcopy(score.bricks[t].cut)
+ score.select_state = 1
+ (self.start_drag_gx, self.start_drag_gy) = (score.bricks[t].cx, score.bricks[t].cy)
+ if score.bricks[t].brick_type == 2:
+ self.main.canvas.move_selection(self.start_drag_gx, self.start_drag_gy, gx, self.start_drag_gy)
+ else:
+ self.main.canvas.move_selection(self.start_drag_gx, self.start_drag_gy, gx, gy)
+ (self.last_gx, self.last_gy) = (gx, gy)
+ elif score.bricks[t].brick_type == 1: # scale brick
+ self.main.canvas.draw_canvas_highlight(1)
+ self.last_gx = 0
+ else:
+ if self.main.score.bricks[self.drag_brick].brick_type == 1:
+ gx, gy = self.main.canvas.within_score(event.x, event.y + self.main.canvas_height)
+ if self.last_gx == -1 and gx != -1 and gy != -1: # within canvas
+ self.main.canvas.draw_canvas_highlight(1)
+ self.last_gx = 0
+ elif self.last_gx == 0 and gx == -1 and gy == -1:
+ self.main.canvas.draw_canvas_highlight(0)
+ self.last_gx = -1
+ else:
+ gx, gy = self.main.canvas.xy2gridxy(event.x, event.y + self.main.canvas_height)
+ if not (gx == self.last_gx and gy == self.last_gy):
+ if self.main.score.bricks[self.drag_brick].brick_type == 0:
+ self.main.canvas.move_selection(self.start_drag_gx, self.start_drag_gy, gx, gy)
+ elif self.main.score.bricks[self.drag_brick].brick_type == 2:
+ self.main.canvas.move_selection(self.start_drag_gx, self.start_drag_gy, gx, self.start_drag_gy)
+ (self.last_gx, self.last_gy) = (gx, gy)
+ else:
+ t = self.is_scrolling(event.x, event.y)
+ if self.scroll_highlight != -1 or t == 1 or t == 4 or t == 5:
+ if t == 1 or t == 4 or t == 5:
+ self.scroll_highlight = t
+ else:
+ self.scroll_highlight = -1
+ cr = self.pixmap.cairo_create()
+ widget = self.widget
+ self.draw_scroll(cr)
+ widget.window.draw_drawable(widget.get_style().fg_gc[gtk.STATE_NORMAL], self.pixmap, self.cx, 0, self.cx, 0, self.sx1-self.sx0, self.height)
+ t = self.is_on_brick(event.x, event.y)
+ if t != self.brick_highlight and (self.brick_highlight != -1 or t != -1):
+ t2 = self.brick_highlight
+ self.brick_highlight = t
+ if t2 != -1:
+ self.draw_1_score(t2)
+ if t != -1:
+ self.draw_1_score(t)
+ t = self.is_on_label(event.x, event.y)
+ if t != self.active_group and t != self.label_highlight and (self.label_highlight != -1 or t != -1):
+ t2 = self.label_highlight
+ self.label_highlight = t
+ cr = self.pixmap.cairo_create()
+ widget = self.widget
+ if t2 != -1:
+ self.draw_label(cr, self.gx0[t2], self.gx1[t2], self.cy - 36, self.group_list[t2], 0, 0)
+ if t != -1:
+ self.draw_label(cr, self.gx0[t], self.gx1[t], self.cy - 36, self.group_list[t], 0, 1)
+ t = self.active_group
+ self.draw_label(cr, self.gx0[t], self.gx1[t], self.cy - 36, self.group_list[t], 1, 1)
+ widget.window.draw_drawable(widget.get_style().fg_gc[gtk.STATE_NORMAL], self.pixmap, self.cx, 0, self.cx, 0, self.sx1-self.sx0, self.height)
+ t = self.is_on_button(event.x, event.y)
+ if t != self.button_highlight and (self.button_highlight != -1 or t != -1):
+ self.button_highlight = t
+ self.draw_buttons()
+
+ def expose_event(self, widget, event):
+ self.widget = widget
+ self.ready = 1
+ cr = self.pixmap.cairo_create()
+
+ # set a clip region for the expose event
+ x , y, width, height = event.area
+ cr.rectangle(x, y, width, height)
+ cr.clip()
+
+ self.draw(cr)
+ self.draw_labels(cr)
+ self.draw_scores()
+
+ widget.window.draw_drawable(widget.get_style().fg_gc[gtk.STATE_NORMAL], self.pixmap, x, y, x, y, width, height)
+
+ return False
+
+ def is_on_button(self, x, y):
+ if x < 12 or x >= self.cx - 12:
+ return -1
+ for i in range(len(self.btns)):
+ if y >= self.cy + i*self.btn_h and y < self.cy + i*self.btn_h + self.btn_h - 8:
+ return i
+ return -1
+
+ def draw_buttons(self):
+ cr = self.pixmap.cairo_create()
+ #cr = self.left_margin_pixmap.cairo_create()
+
+ cr.set_source_rgb(0.72, 0.78, 0.9)
+ cr.rectangle(0, 0, self.cx, self.height)
+ cr.fill()
+
+ widget = self.widget
+ cr.set_font_size(18)
+ for i in range(len(self.btns)):
+ (x0, y0) = (12, self.cy + i * self.btn_h)
+ (x1, y1) = (self.cx-12, self.cy + i * self.btn_h + self.btn_h-8)
+ self.draw_curvy_rectangle(cr, x0, y0, x1, y1, 4, (self.button_highlight == i))
+ xb, yb, wid, hei = cr.text_extents(self.btns[i])[:4]
+ cr.set_source_rgb(0.4, 0.4, 0.4)
+ cr.move_to( (x0+x1)/2 - wid/2 - xb, (y0+y1)/2 - hei/2 - yb)
+ cr.show_text(self.btns[i])
+ widget.window.draw_drawable(widget.get_style().fg_gc[gtk.STATE_NORMAL], self.pixmap, 0, 0, 0, 0, self.cx-3, self.height)
+
+ def draw_score_util(self, cr, sx, map, cut, wid = 64):
+ fx = -1
+ for k in range(self.ngrid_h):
+ if fx != -1 and k-fx >= wid:
+ continue;
+ for i in range(8):
+ for j in range(self.ngrid_v):
+ if map[7-i][k][j] != 0 and (k==0 or map[7-i][k-1][j] == 0 or cut[7-i][k-1][j] == 1):
+ if fx == -1:
+ fx = k
+ len = 1
+ while cut[7-i][k+len-1][j] == 0 and k-fx+len < wid and k+len < self.ngrid_h and map[7-i][k+len][j] != 0:
+ len = len + 1
+ v = map[7-i][k][j]
+ self.draw_note(cr, sx, k - fx, j, len, 7-i, v)
+
+ def draw_mini_score(self, cr, sx, brick, flag):
+ self.draw_score_canvas(cr, sx, brick.swid, flag)
+ if brick.is_blank == 0:
+ self.draw_score_util(cr, sx, brick.map, brick.cut)
+
+ def is_on_label(self, x, y):
+ if y < self.cy - 36 or y >= self.cy - 6:
+ return -1
+ for i in range(len(self.group_list)):
+ if x >= self.gx0[i] and x < self.gx1[i]:
+ return i
+ return -1
+
+ def is_scrolling(self, x, y):
+ y0 = self.cy + self.chei + 2
+ if y < y0 or y >= y0 + 22:
+ return -1
+ if x < self.sx0 or x >= self.sx1:
+ return -1
+ if x >= self.sx0 + self.scroll_x + 22 and x < self.sx0 + self.scroll_x + 22 + self.scroll_width:
+ return 1
+ if x < self.sx0 + self.scroll_x + 22:
+ if x < self.sx0 + 22:
+ return 4 # left button
+ return 2
+ if x >= self.sx1 - 22:
+ return 5 # right button
+ return 3
+
+ def is_on_brickarea(self, x, y):
+ if y < self.cy - 2 or y > self.cy + self.chei + 2:
+ return False
+ if x < self.sx0 or x > self.sx1:
+ return False
+ return True
+
+ def is_on_brick(self, ex, y):
+ if y < self.cy - 2 or y > self.cy + self.chei + 2:
+ return -1
+ if self.max_sx == 0:
+ x = 5
+ else:
+ xoffset = (self.bricks_total_width - self.sx1 + self.sx0) * self.scroll_x / self.max_sx
+ x = -xoffset + 5
+ for i in range(self.bricks_cnt):
+ brick = self.main.score.bricks[i]
+ if (x + brick.width * self.gridw) >= 0 and x < (self.sx1 - self.sx0):
+ if ex >= self.cx + x and ex < self.cx + x + brick.width * self.gridw:
+ return i
+ x = x + brick.width * self.gridw + 10
+ if self.active_group == 0:
+ if (x + 50) >= 0 and x < (self.sx1 - self.sx0):
+ if ex >= self.cx + x and ex < self.cx + x + 50 and y >= self.cy + self.chei/3 and y < self.cy + self.chei/3 + 22:
+ return self.bricks_cnt
+ elif self.active_group == 6:
+ if (x + 50) >= 0 and x < (self.sx1 - self.sx0):
+ if ex >= self.cx + x and ex < self.cx + x + 50 and y >= self.cy + self.chei/3 and y < self.cy + self.chei/3 + 22:
+ return self.bricks_cnt
+ return -1
+
+ def update_scroll(self, target = -1, stay_in_max = 0):
+ self.bricks_total_width = 0
+ w = self.sx1 - self.sx0
+ for i in range(self.bricks_cnt):
+ self.bricks_total_width = self.bricks_total_width + self.main.score.bricks[i].width*self.gridw
+ if self.active_group == 0 and i == self.bricks_cnt - 1:
+ self.bricks_total_width = self.bricks_total_width + 40
+ elif self.active_group == 6 and i == self.bricks_cnt - 1:
+ self.bricks_total_width = self.bricks_total_width + 70
+ else:
+ self.bricks_total_width = self.bricks_total_width + self.bdiv
+
+ if self.bricks_total_width > (self.sx1 - self.sx0):
+ self.scroll_width = (self.sx1 - self.sx0) * (self.sx1 - self.sx0 - 44) / self.bricks_total_width
+ else:
+ self.scroll_width = (self.sx1 - self.sx0 - 44)
+ self.max_sx = self.sx1-self.sx0-44-self.scroll_width
+ if stay_in_max == 1 or self.scroll_x > self.max_sx:
+ self.scroll_x = self.max_sx
+
+ def draw_curvy_rectangle(self, cr, x0, y0, x1, y1, r, highlight):
+ if highlight == 0:
+ cr.set_source_rgb(0.80,0.80,0.80)
+ else:
+ cr.set_source_rgb(0.92,0.92,0.92)
+ cr.move_to(x0, y0 + r)
+ cr.curve_to(x0, y0, x0, y0, x0+r, y0)
+ cr.line_to(x1-r, y0)
+ cr.curve_to(x1, y0, x1, y0, x1, y0+r)
+ cr.line_to(x1, y1-r)
+ cr.curve_to(x1, y1, x1, y1, x1-r, y1)
+ cr.line_to(x0+r, y1)
+ cr.curve_to(x0, y1, x0, y1, x0, y1-r)
+ cr.close_path()
+ cr.fill_preserve()
+ cr.set_line_width(1)
+ cr.set_source_rgb(0.98, 0.98, 0.98)
+ cr.stroke()
+
+ def draw_active_rectangle(self, cr, x0, y0, x1, y1, r, frame_only = 0):
+ x00 = self.sx0 - 2
+ x2 = self.sx1 + 2
+ y2 = self.cy + self.chei + 24
+ cr.set_source_rgb(0.92,0.92,0.92)
+ if frame_only == 1:
+ cr.rectangle(x0, y0, x1-x0, y1-y0+1)
+ cr.fill()
+ cr.move_to(x0, y0 + r)
+ cr.curve_to(x0, y0, x0, y0, x0+r, y0)
+ cr.line_to(x1-r, y0)
+ cr.curve_to(x1, y0, x1, y0, x1, y0+r)
+ cr.line_to(x1, y1-r)
+ cr.curve_to(x1, y1, x1, y1, x1+r, y1)
+ cr.line_to(x2-r, y1)
+ cr.curve_to(x2, y1, x2, y1, x2, y1+r)
+ cr.line_to(x2, y2-r)
+ cr.curve_to(x2, y2, x2, y2, x2-r, y2)
+ cr.line_to(x00+r, y2)
+ cr.curve_to(x00, y2, x00, y2, x00, y2-r)
+ cr.line_to(x00, y1+r)
+ cr.curve_to(x00, y1, x00, y1, x00+r, y1)
+ cr.line_to(x0-r, y1)
+ cr.curve_to(x0, y1, x0, y1, x0, y1-r)
+ cr.close_path()
+ if frame_only == 0:
+ cr.fill_preserve()
+ cr.set_line_width(1)
+ cr.set_source_rgb(0.98, 0.98, 0.1)
+ cr.stroke()
+
+ def draw_label(self, cr, x0, x1, y, text, active = 0, highlight = 0):
+ cr.set_font_size(18)
+ x_bearing, y_bearing, width, height = cr.text_extents(text)[:4]
+
+ y0 = y
+ y1 = y + 18 + 12
+ r = 4
+
+ if active == 0:
+ self.draw_curvy_rectangle(cr, x0, y0, x1, y1, r, highlight)
+ else:
+ self.draw_active_rectangle(cr, x0, y0, x1, y1, r, highlight) # last parameter served as frame_only flag
+
+ cr.set_source_rgb(0.4, 0.4, 0.4)
+ #cr.select_font_face("Georgia",
+ # cairo.FONT_SLANT_NORMAL, cairo.FONT_WEIGHT_BOLD)
+ cr.move_to(x0 + 6 - x_bearing, y + 6 - y_bearing)
+ cr.show_text(text)
+
+ def measure_text(self, cr):
+ cr.set_font_size(18)
+ t = 12
+ for i in range(len(self.group_list)):
+ x_bearing, y_bearing, width, height = cr.text_extents(self.group_list[i])[:4]
+ self.gx0[i] = self.cx + t
+ self.gx1[i] = self.cx + t + width + 12
+ t = t + width + 12 + 8
+
+ def draw_labels(self, cr, f = 0):
+ if self.gx0[0] == -1:
+ self.measure_text(cr)
+ for i in range(len(self.group_list)):
+ if self.active_group != i:
+ self.draw_label(cr, self.gx0[i], self.gx1[i], self.cy - 36, self.group_list[i])
+ i = self.active_group
+ self.draw_label(cr, self.gx0[i], self.gx1[i], self.cy - 36, self.group_list[i], 1, f)
+
+ def draw_scroll(self, cr):
+ self.update_scroll()
+
+ x0, y0 = self.sx0 , self.cy + self.chei
+ x1, y1 = self.sx1, y0 + 22
+ cr.set_source_rgb(0.72, 0.78, 0.9)
+ cr.rectangle(x0, y0, x1-x0, y1-y0)
+ cr.fill()
+ cr.set_source_rgb(0.72 * 0.8, 0.78 * 0.8, 0.9 * 0.8)
+ cr.rectangle(x0+16, y0, x1-x0-32, y1-y0)
+ cr.fill()
+ cr.set_source_rgb(0.95, 0.95, 0.95)
+ self.draw_scroll_btn(cr, x0, y0, 20, 0, (self.scroll_highlight == 4))
+ self.draw_scroll_btn(cr, x1 - 22, y0, 20, 1, (self.scroll_highlight == 5))
+ self.draw_scroll_btn(cr, x0 + 22 + self.scroll_x, y0, self.scroll_width, 2, (self.scroll_highlight == 1))
+
+ def draw_1_score(self, target):
+ cr = self.pixmap.cairo_create()
+ widget = self.widget
+
+ if self.max_sx != 0:
+ xoffset = (self.bricks_total_width - self.sx1 + self.sx0) * self.scroll_x / self.max_sx
+ else:
+ xoffset = 0
+ x = -xoffset + 5
+ for i in range(self.bricks_cnt+1):
+ if i == self.bricks_cnt:
+ if self.active_group == 0: # add brick button
+ if i == target:
+ if x + 40 >= 0 and x < (self.sx1 - self.sx0):
+ self.draw_scroll_btn(cr, self.cx + x, self.cy + self.chei/3, 22, 3, i == self.brick_highlight)
+ if self.active_group == 6: # clear brick button
+ if i == target:
+ if x + 80 >= 0 and x < (self.sx1 - self.sx0):
+ self.draw_scroll_btn(cr, self.cx + x, self.cy + self.chei/3, 60, 4, i == self.brick_highlight)
+ else:
+ brick = self.main.score.bricks[i]
+ if (x + brick.width * self.gridw) >= 0 and x < (self.sx1 - self.sx0) and i == target:
+ self.draw_mini_score(cr, x, brick, i == self.brick_highlight or self.active_group == 3 and self.main.score.scale_mode == i)
+ x = x + brick.width * self.gridw + self.bdiv
+ widget.window.draw_drawable(widget.get_style().fg_gc[gtk.STATE_NORMAL], self.pixmap, self.cx, 0, self.cx, 0, self.sx1-self.sx0, self.height)
+
+ def draw_1_score_b(self, target, map, cut):
+ cr = self.pixmap.cairo_create()
+ widget = self.widget
+
+ if self.max_sx != 0:
+ xoffset = (self.bricks_total_width - self.sx1 + self.sx0) * self.scroll_x / self.max_sx
+ else:
+ xoffset = 0
+ x = -xoffset + 5
+ for i in range(self.bricks_cnt):
+ brick = self.main.score.bricks[i]
+ if (x + brick.width * self.gridw) >= 0 and x < (self.sx1 - self.sx0) and i == target:
+ self.draw_score_canvas(cr, x, brick.swid, 1)
+ self.draw_score_util(cr, x, map, cut, brick.swid)
+ x = x + brick.width * self.gridw + self.bdiv
+ widget.window.draw_drawable(widget.get_style().fg_gc[gtk.STATE_NORMAL], self.pixmap, self.cx, 0, self.cx, 0, self.sx1-self.sx0, self.height)
+
+ def draw_scores(self):
+ self.draw_buttons()
+
+ cr = self.pixmap.cairo_create()
+ widget = self.widget
+ self.draw_scroll(cr)
+
+ cr.set_source_rgb(0.72, 0.78, 0.9)
+ cr.rectangle(self.cx+2, self.cy-5, self.sx1-self.sx0, self.chei+6)
+ cr.fill()
+ if self.max_sx != 0:
+ xoffset = (self.bricks_total_width - self.sx1 + self.sx0) * self.scroll_x / self.max_sx
+ else:
+ xoffset = 0
+ x = -xoffset + 5
+ for i in range(self.bricks_cnt+1):
+ if i == self.bricks_cnt:
+ if self.active_group == 0: # add brick button
+ if x + 40 >= 0 and x < (self.sx1 - self.sx0):
+ self.draw_scroll_btn(cr, self.cx + x, self.cy + self.chei/3, 22, 3, i == self.brick_highlight)
+ elif self.active_group == 6: # clear brick button
+ if x + 80 >= 0 and x < (self.sx1 - self.sx0):
+ self.draw_scroll_btn(cr, self.cx + x, self.cy + self.chei/3, 60, 4, i == self.brick_highlight)
+ else:
+ brick = self.main.score.bricks[i]
+ if (x + brick.width * self.gridw) >= 0 and x < (self.sx1 - self.sx0):
+ self.draw_mini_score(cr, x, brick, (i == self.brick_highlight or self.active_group == 3 and self.main.score.scale_mode == i))
+ x = x + brick.width * self.gridw + self.bdiv
+ widget.window.draw_drawable(widget.get_style().fg_gc[gtk.STATE_NORMAL], self.pixmap, self.cx, 0, self.cx, 0, self.sx1-self.sx0, self.height)
+
+ def draw(self, cr):
+ cr.set_source_rgb(0.72, 0.78, 0.9)
+ cr.rectangle(0, 0, self.width, self.height)
+ cr.fill()
+
+ def draw_note(self, cr, sx, gx, gy, len, c, v): # given a cairo_context and the location of note, draw the note (frame and color)
+ x0, y0 = self.cx+sx + gx*self.gridw, self.cy+gy*self.gridh
+ x1, y1 = x0+self.gridw*len+1, y0+self.gridh
+ r = self.gridw/2
+
+ self.main.canvas.set_color(cr, c, v)
+ cr.rectangle(x0, y0, x1-x0, y1-y0)
+# cr.move_to(x0, y0 + r)
+# cr.curve_to(x0, y0, x0, y0, x0+r, y0)
+# cr.line_to(x1-r, y0)
+# cr.curve_to(x1, y0, x1, y0, x1, y0+r)
+# cr.line_to(x1, y1-r)
+# cr.curve_to(x1, y1, x1, y1, x1-r, y1)
+# cr.line_to(x0+r, y1)
+# cr.curve_to(x0, y1, x0, y1, x0, y1-r)
+# cr.close_path()
+ cr.fill_preserve()
+ cr.set_line_width(0.6)
+ cr.set_source_rgb(0.5, 0.5, 0.5)
+ cr.stroke()
+
+ def draw_score_canvas(self, cr, sx, h, flag):
+ x0, y0 = self.cx + sx-2, self.cy-2
+ x1, y1 = x0+self.gridw*h+5, y0+self.gridh*self.ngrid_v+4
+ r = (y1-y0) / 6
+ if (x1-x0) / 4 < r:
+ r = (x1-x0) / 4
+ if flag:
+ cr.set_source_rgb(0.99, 0.99, 0.99)
+ else:
+ cr.set_source_rgb(0.9, 0.9, 0.9)
+ cr.move_to(x0, y0 + r)
+ cr.curve_to(x0, y0, x0, y0, x0+r, y0)
+ cr.line_to(x1-r, y0)
+ cr.curve_to(x1, y0, x1, y0, x1, y0+r)
+ cr.line_to(x1, y1-r)
+ cr.curve_to(x1, y1, x1, y1, x1-r, y1)
+ cr.line_to(x0+r, y1)
+ cr.curve_to(x0, y1, x0, y1, x0, y1-r)
+ cr.close_path()
+ cr.fill_preserve()
+ cr.set_line_width(2)
+ cr.set_source_rgb(0.5, 0.5, 0.5)
+ cr.stroke()
+
+ def draw_scroll_btn(self, cr, x, y, w, opt, h):
+ x0, y0 = x+1, y+1
+ x1, y1 = x0+w, y0+20
+ if opt == 4:
+ y1 = y0 + 26
+ r = 10
+
+ if opt == 3 or opt == 4:
+ if h== 1:
+ cr.set_source_rgb(0.9, 0.9, 0.1)
+ else:
+ cr.set_source_rgb(0.9, 0.9, 0.9)
+ else:
+ if h == 1:
+ cr.set_source_rgb(0.85,0.85,0.98)
+ else:
+ cr.set_source_rgb(0.75,0.75,0.95)
+ cr.move_to(x0, y0 + r)
+ cr.curve_to(x0, y0, x0, y0, x0+r, y0)
+ cr.line_to(x1-r, y0)
+ cr.curve_to(x1, y0, x1, y0, x1, y0+r)
+ cr.line_to(x1, y1-r)
+ cr.curve_to(x1, y1, x1, y1, x1-r, y1)
+ cr.line_to(x0+r, y1)
+ cr.curve_to(x0, y1, x0, y1, x0, y1-r)
+ cr.close_path()
+ cr.fill_preserve()
+ cr.set_line_width(1)
+ cr.set_source_rgb(0.98, 0.98, 0.98)
+ cr.stroke()
+
+ if opt == 0:
+ cr.set_source_rgb(0.4, 0.4, 0.9)
+ cr.move_to(x0+14, y0+3)
+ cr.line_to(x0+6, y0+10)
+ cr.line_to(x0+14, y0+17)
+ cr.set_line_width(2)
+ cr.stroke()
+ elif opt == 1:
+ cr.set_source_rgb(0.4, 0.4, 0.9)
+ cr.move_to(x0+6, y0+3)
+ cr.line_to(x0+14, y0+10)
+ cr.line_to(x0+6, y0+17)
+ cr.set_line_width(2)
+ cr.stroke()
+ elif opt == 3:
+ cr.set_source_rgb(0.8, 0, 0)
+ cr.move_to(x0+5, y0+10)
+ cr.line_to(x0+17, y0+10)
+ cr.move_to(x0+11, y0+4)
+ cr.line_to(x0+11, y0+16)
+ cr.set_line_width(2)
+ cr.stroke()
+ elif opt == 4:
+ cr.set_font_size(18)
+ x_bearing, y_bearing, width, height = cr.text_extents("Clear")[:4]
+ cr.set_source_rgb(0.4, 0.4, 0.4)
+ cr.move_to(x0 + 8 - x_bearing, y0 + 6 - y_bearing)
+ cr.show_text("Clear")
diff --git a/Canvas.py b/Canvas.py
new file mode 100644
index 0000000..7cb75ae
--- /dev/null
+++ b/Canvas.py
@@ -0,0 +1,1502 @@
+import gtk
+import time
+import math
+
+from copy import deepcopy
+from Musicpainter import *
+
+_showGraphcisEvent = False
+
+class Canvas(gtk.DrawingArea):
+
+ def __init__(self, wid, hei, platform, mp):
+
+ self.main = mp
+ self.platform = platform
+ self.width, self.height = wid, hei
+
+ self.init_data()
+ self.init_graphics()
+ gtk.DrawingArea.__init__(self)
+
+ self.set_size_request(self.width, self.height)
+
+ # Event signals
+ self.connect("expose_event", self.expose_event)
+ self.connect("configure_event", self.configure_event)
+ self.connect("enter_notify_event", self.enter_notify_event)
+ self.connect("leave_notify_event", self.leave_notify_event)
+ self.connect("motion_notify_event", self.motion_notify_event)
+ self.connect("button_press_event", self.button_press_event)
+ self.connect("button_release_event", self.button_release_event)
+
+ self.set_events(gtk.gdk.EXPOSURE_MASK
+ | gtk.gdk.ENTER_NOTIFY_MASK
+ | gtk.gdk.LEAVE_NOTIFY_MASK
+ | gtk.gdk.BUTTON_PRESS_MASK
+ | gtk.gdk.BUTTON_RELEASE_MASK
+ | gtk.gdk.POINTER_MOTION_MASK
+ | gtk.gdk.POINTER_MOTION_HINT_MASK)
+ def zeros(self, n1, n2):
+ array = [[0 for i in range(n2)] for j in range(n1)]
+ return array
+
+ def init_data(self):
+
+ self.ready = 0
+
+ self.button_highlight = -1
+
+ if self.platform == "sugar-xo":
+ self.btns = ["Explore", "Load", "Clear"]
+ else:
+ self.btns = ["Explore", "Load", "Save", "Clear", "Quit"]
+
+ self.dblclick_state = 0
+ self.fix_button = 0
+ self.just_clean = 0
+ self.last_gx_key = -1
+ self.last_gx, self.last_gy = -1, -1
+ self.start_drag_gx, self.start_drag_gy = -1, -1
+ self.rec_gx, self.rec_gy = -1, -1
+ self.ngrid_h = 64
+ self.ngrid_v = 18
+ self.drag_state = 0
+ self.last_hgx = -1
+ self.cursor_x = -1
+ (self.tsx, self.tsy) = (-1, -1)
+ (self.tgx, self.tgy) = (-1, -1)
+
+ self.mask = self.zeros(self.ngrid_h, self.ngrid_v)
+ self.mask_buf = self.zeros(self.ngrid_h, self.ngrid_v)
+ self.umask = self.zeros(self.ngrid_h, self.ngrid_v)
+
+ def init_graphics(self):
+ self.cx = (int)(0.09 * self.width)
+ self.cy = 16
+
+ self.btn_h = 42
+
+# print str(self.width) + "," + str(self.height)
+
+ vh = 1.0 * (self.width - 1.33 * self.cx) / self.ngrid_h
+ self.gridw = (int)(vh)
+ vv = 1.0 * (self.height - self.cy - self.cy) / self.ngrid_v
+ self.gridh = (int)(vv)
+
+# if self.platform == "sugar-xo":
+# self.gridh = 30
+# self.gridw = 16
+# else: # "windows-1024", default
+# self.gridh = 22
+# self.gridw = 14
+
+
+ self.blue = gtk.gdk.Color(0,1280,57600)
+ self.green = gtk.gdk.Color(9728,38912,4608)
+ self.red = gtk.gdk.Color(65535,15000,15000)
+ self.yellow = gtk.gdk.Color(64000, 65000, 500)
+ self.purple = gtk.gdk.color_parse('purple')
+ self.orange = gtk.gdk.color_parse('orange')
+ self.lblue = gtk.gdk.Color(0, 65535, 65535)
+ self.grass = gtk.gdk.Color(41728, 63744, 512)
+
+ self.color_list = [self.red,self.orange,self.yellow,self.grass,self.green,self.lblue,self.blue,self.purple]
+
+ def expose_event(self, widget, event):
+ cr = self.pixmap.cairo_create()
+
+ # set a clip region for the expose event
+ x , y, width, height = event.area
+ cr.rectangle(x, y, width, height)
+ cr.clip()
+
+ self.draw_canvas(cr)
+ self.draw_score(cr)
+ self.draw_buttons(cr)
+
+ self.widget = widget
+ self.ready = 1
+ widget.window.draw_drawable(widget.get_style().fg_gc[gtk.STATE_NORMAL], self.pixmap, x, y, x, y, width, height)
+ return False
+
+ # =====================================================================================================================================================
+
+ def configure_event(self, widget, event):
+ x, y, width, height = widget.get_allocation()
+# print "configure_event width = " + str(width) + ", height = " + str(height)
+ self.pixmap = gtk.gdk.Pixmap(widget.window, width, height)
+ return True
+
+ def enter_notify_event(self, widget, event):
+# print "canvas.enter"
+ self.main.cursor_area = 2
+ self.main.grab_focus()
+
+ def leave_notify_event(self, widget, event):
+# print "canvas.leave"
+ if self.main.cursor_area == 2:
+ self.main.cursor_area = 0
+ if self.main.toolbar.toolsel == 1:
+ return
+ self.clear_grid_cursor(widget, self.main.toolbar.toolsel)
+ (self.last_gx, self.last_gy) = (-1, -1)
+
+ def button_press_event(self, widget, event):
+# print "canvas.mouse_btn_press (%d,%d)" % (event.x, event.y)
+ self.fix_button = self.fix_button + 1
+ if self.fix_button != 1:
+ return
+ if event.button == 1:
+ gx, gy = self.within_score(event.x, event.y)
+ #print "gx,gy = (%d,%d)" % (gx, gy)
+ toolbar = self.main.toolbar
+ score = self.main.score
+ if gx!=-1: # if the cursor is within the score area
+ if toolbar.toolsel == 1:
+ if self.dblclick_state == 2 and self.last_drag_gx == gx and self.last_drag_gy == gy:
+ self.dblclick_state = 3
+ else:
+ self.dblclick_state = 1
+ (self.last_drag_gx, self.last_drag_gy) = (gx, gy)
+ if toolbar.toolsel == 2 or toolbar.toolsel == 3 or toolbar.toolsel == 4:
+ if score.select_state == 1:
+ score.de_selection()
+ self.draw_deselection()
+ if self.is_rec() and self.cursor_x != -1 and toolbar.toolsel == 2:
+ gx = self.cursor_x
+ self.rec_gx = gx
+ self.rec_gy = gy
+ self.draw_cell(widget, gx, gy, True)
+ else:
+ self.draw_cell(widget, gx, gy)
+ self.just_clean = 0
+ elif toolbar.toolsel == 1: # region-selecting mode
+ (self.start_drag_gx, self.start_drag_gy) = (gx, gy)
+ if score.select_state == 1:
+ if self.is_cursor_on_selection(gx, gy):
+ score.drag = deepcopy(score.sel)
+ score.dcut = deepcopy(score.scut)
+ self.drag_state = 1
+ else:
+ if self.main.press_ctrl == 0: # if has current selection but not in union mode, de-select first
+ score.de_selection()
+ self.draw_deselection()
+ self.draw_grid_cursor(widget, gx, gy, toolbar.toolsel)
+ else:
+ self.draw_grid_cursor(widget, gx, gy, toolbar.toolsel)
+ elif toolbar.toolsel <= 0: # f or p
+ if toolbar.toolsel == 0 and toolbar.fstate != 0 or toolbar.toolsel == -1 and toolbar.pstate != 0: # region_mode
+ (self.start_drag_gx, self.start_drag_gy) = (gx, gy)
+ self.draw_grid_cursor(widget, gx, gy, toolbar.toolsel)
+ else:
+ v = self.adjust_volume(gx, gy, toolbar.toolsel)
+ if v != -1:
+ self.main.score.drag_on_vol(self.main.csound, toolbar.toolsel, toolbar.colorsel, gy, v)
+ else:
+ t = self.is_on_button(event.x, event.y)
+ if self.platform == "sugar-xo" and t == 2:
+ t = 3
+# if t == 0: # Play
+# self.main.score.play_music(self.main.csound)
+# elif t == 1: # Stop
+# self.main.score.stop_music(self.main.csound)
+ if t == 0: # Explore
+ browser = self.main.browser
+ if browser.flag == 0:
+ self.main.bricksarea.change_into_browser()
+ self.fix_button = 0
+ self.main.author_box.set_active(0)
+ self.main.type_box.set_active(0)
+ self.main.scale_box.set_active(0)
+ browser.flag = 3
+ elif t == 1: # Load
+ if score.select_state == 1:
+ score.de_selection()
+ self.draw_deselection()
+ browser = self.main.browser
+ if browser.flag == 0:
+ self.main.bricksarea.change_into_browser()
+ self.fix_button = 0
+ self.main.author_box.set_active(1)
+ self.main.type_box.set_active(0)
+ self.main.scale_box.set_active(0)
+ browser.flag = 3
+ elif t == 2: # Save
+ self.save_file()
+ elif t == 3: # Clear
+ self.main.score.filename = ""
+ self.main.score.note = ""
+ self.main.score.title = ""
+ self.main.score.description = ""
+ self.main.score.clear_score()
+ cr = self.pixmap.cairo_create()
+ self.draw_canvas(cr)
+ self.draw_buttons(cr)
+ self.draw_score(cr)
+ widget = self.widget
+ widget.window.draw_drawable(widget.get_style().fg_gc[gtk.STATE_NORMAL], self.pixmap, 0, 0, 0, 0, self.width, self.height)
+ elif t == 4: # Quit
+ if self.main.bricksarea.brick_added:
+ flag = False
+ for i in range(self.main.score.work_bricks_cnt):
+# print self.main.score.work_bricks[i].is_blank
+ if self.main.score.work_bricks[i].is_blank == 0:
+ flag = True
+ break
+ if flag:
+ if self.platform == "sugar-xo":
+ self.main.window.set_canvas(self.main.msg1_layout)
+ else:
+ self.main.window.remove(self.main.layout)
+ self.main.window.add(self.main.msg1_layout)
+ self.main.now_layout = self.main.msg1_layout
+ self.main.window.show_all()
+ self.fix_button = 0
+ else:
+ self.main.destroy0(widget)
+ else:
+ self.main.destroy0(widget)
+
+ return True
+
+ def save_file(self):
+ score = self.main.score
+ if score.select_state == 1:
+ score.de_selection()
+ self.draw_deselection()
+ if self.main.score.filename == "":
+ self.main.score.filename = self.main.username + "_0_" + str(self.main.score.scale_mode) + "_piece" + str(random.randint(0, 999999)) + ".mps"
+ if self.main.save_as:
+ self.main.save_as = False
+ self.main.sbutton2.set_no_show_all(False)
+ self.main.sbutton2.show()
+ else:
+ [a, ty, s] = self.main.browser.get_file_info(self.main.score.filename)
+ if a != self.main.username:
+ self.main.score.note = "Based on " + self.main.score.filename+ " - " + self.main.score.note
+ self.main.score.filename = self.main.username + "_0_" + str(self.main.score.scale_mode) + "_piece" + str(random.randint(0, 999999)) + ".mps"
+ if not self.main.save_as:
+ self.main.save_as = True
+ self.main.sbutton2.set_no_show_all(True)
+ self.main.sbutton2.hide()
+ else:
+ if self.main.save_as:
+ self.main.save_as = False
+ self.main.sbutton2.set_no_show_all(False)
+ self.main.sbutton2.show()
+
+ if self.platform == "sugar-xo":
+ self.main.window.set_canvas(self.main.msg2_layout)
+ else:
+ self.main.window.remove(self.main.layout)
+ self.main.window.add(self.main.msg2_layout)
+ self.main.mlabel3.set_text("Author: " + self.main.username)
+ self.main.mlabel4.set_text("Scale: " + self.main.score.scale_list[self.main.score.scale_mode])
+ self.main.mlabel5.set_text("Filename: " + self.main.score.filename)
+ self.main.entry2.set_text(self.main.score.title)
+ self.main.entry3.set_text(self.main.score.description)
+ self.main.entry4.set_text(self.main.score.note)
+ self.main.window.show_all()
+ self.main.key_lock = 1
+ self.fix_button = 0
+
+ def canvas_load_score(self, filename):
+ #if self.main.score.is_edited:
+ #self.main.window.remove(self.main.layout)
+ #self.main.window.add(self.main.msg1_layout)
+ #self.main.mlabel1.set_text("Do you want to save")
+ #self.main.mlabel2.set_text("your current work?")
+ #self.main.window.show_all()
+ #self.load_pending = filename
+ #return
+ self.main.score.read_mpscore(filename)
+ self.update_top()
+ cr = self.pixmap.cairo_create()
+ self.draw_canvas(cr)
+ self.draw_buttons(cr)
+ self.draw_score(cr)
+ widget = self.widget
+ widget.window.draw_drawable(widget.get_style().fg_gc[gtk.STATE_NORMAL], self.pixmap, 0, 0, 0, 0, self.width, self.height)
+ self.main.score.is_edited = False
+ self.main.window.set_title("Music Painter - " + self.main.username)
+ #self.main.window.show_all()
+
+ def canvas_load_journal(self, filename):
+ try:
+ self.main.score.read_journal(filename)
+ except:
+ print "read journal exception caught"
+ #print "update top"
+ self.update_top()
+ cr = self.pixmap.cairo_create()
+ self.draw_canvas(cr)
+ self.draw_buttons(cr)
+ self.draw_score(cr)
+ widget = self.widget
+ widget.window.draw_drawable(widget.get_style().fg_gc[gtk.STATE_NORMAL], self.pixmap, 0, 0, 0, 0, self.width, self.height)
+ self.main.score.is_edited = False
+ self.main.window.set_title("Music Painter - " + self.main.username)
+ #self.main.window.show_all()
+
+ def button_release_event(self, widget, event):
+# print "canvas.mouse_btn_release (%d,%d)" % (event.x, event.y)
+ self.fix_button = 0
+ self.just_clean = 0
+ self.rec_gx = self.rec_gy = -1
+ toolbar = self.main.toolbar
+ if toolbar.toolsel==1: # region-selecting mode
+ gx, gy = self.within_score(event.x, event.y)
+ if self.dblclick_state == 1 and gx == self.start_drag_gx and gy == self.start_drag_gy:
+ if self.drag_state == 1:
+ self.drag_state = 0
+ else:
+ self.do_select_region(self.start_drag_gx, self.start_drag_gy, self.last_gx, self.last_gy, 1)
+ self.draw_grid_cursor(widget, -1, -1, toolbar.toolsel)
+ self.dblclick_state = 2
+ (self.last_drag_gx, self.last_drag_gy) = (gx, gy)
+ elif self.dblclick_state == 3 and gx == self.start_drag_gx and gy == self.start_drag_gy:
+ if self.drag_state == 1:
+ self.drag_state = 0
+ self.draw_grid_cursor(widget, -1, -1, toolbar.toolsel)
+ cr = self.pixmap.cairo_create()
+ self.do_select_same_color(widget, cr, gx, gy)
+ widget.window.draw_drawable(widget.get_style().fg_gc[gtk.STATE_NORMAL], self.pixmap, 0, 0, 0, 0, self.width, self.height)
+ self.dblclick_state = 0
+ else:
+ self.dblclick_state = 0
+ if self.drag_state == 1:
+ self.drag_state = 0
+ bricka = self.main.bricksarea
+ score = self.main.score
+ t = bricka.is_on_brick(event.x, event.y - self.main.canvas_height)
+ if t != -1 and t != bricka.bricks_cnt:
+ score.bricks[t].dump_score(score.drag, score.dcut, score.scale_mode, score.key_shift)
+ score.bricks[t].sval = self.main.toolbar.sval
+ score.bricks[t].filename = ""
+ bricka.draw_scores()
+ else:
+ self.do_select_region(self.start_drag_gx, self.start_drag_gy, self.last_gx, self.last_gy, 1)
+ self.draw_grid_cursor(widget, -1, -1, toolbar.toolsel)
+ (self.start_drag_gx, self.start_drag_gy) = (-1, -1)
+ elif toolbar.toolsel == -1 and toolbar.pstate != 0 or toolbar.toolsel == 0 and toolbar.fstate != 0:
+ if toolbar.toolsel == -1 and toolbar.pstate == 1:
+ mode = 0
+ elif toolbar.toolsel == -1 and toolbar.pstate == 2:
+ mode = 2
+ elif toolbar.toolsel == 0 and toolbar.fstate == 1:
+ mode = 1
+ elif toolbar.toolsel == 0 and toolbar.fstate == 2:
+ mode = 3
+ self.draw_grid_cursor(widget, -1, -1, 1)
+ self.adjust_volume_in_selected_region(self.start_drag_gx, self.start_drag_gy, self.last_gx, self.last_gy, mode)
+ (self.start_drag_gx, self.start_drag_gy) = (-1, -1)
+ self.main.score.drag_off(self.main.csound, toolbar.toolsel, toolbar.colorsel) # note_off
+ return
+
+ def is_rec(self):
+ return (self.main.score.play_state != -2 and self.main.toolbar.record == 1)
+
+ def motion_notify_event(self, widget, event):
+ if self.ready == 0:
+ return
+ if event.is_hint:
+ x, y, state = event.window.get_pointer()
+ else:
+ x, y = event.x, event.y
+ state = event.state
+
+ if state & gtk.gdk.BUTTON1_MASK:
+ gx, gy = self.within_score(event.x, event.y)
+ toolbar = self.main.toolbar
+ if gx!=-1 and (toolbar.toolsel == 2 or toolbar.toolsel == 3):
+ if self.is_rec() == 1 and self.cursor_x != -1 and toolbar.toolsel == 2:
+ gx = self.cursor_x
+ if self.rec_gx == gx and self.rec_gy != gy:
+ self.erase_cell(widget, gx, self.rec_gy)
+ self.draw_cell(widget, gx, gy, True)
+ self.rec_gx = gx
+ self.rec_gy = gy
+ elif not (gx == self.last_drag_gx and gy == self.last_drag_gy):
+ self.draw_cell(widget, gx, gy)
+ (self.last_drag_gx, self.last_drag_gy) = (gx, gy)
+ if gx!=-1 and (toolbar.toolsel == -1 and toolbar.pstate == 0 or toolbar.toolsel == 0 and toolbar.fstate == 0) and not (gx == self.last_drag_gx and gy == self.last_drag_gy):
+ v = self.adjust_volume(gx, gy, toolbar.toolsel)
+ if v != -1:
+ self.main.score.drag_on_vol(self.main.csound, toolbar.toolsel, toolbar.colorsel, gy, v)
+ (self.last_drag_gx, self.last_drag_gy) = (gx, gy)
+ if self.drag_state == 1:
+ if (self.dblclick_state == 1 or self.dblclick_state == 3) and (self.start_drag_gx != gx or self.start_drag_gy != gy):
+ self.dblclick_state = 0
+ bricka = self.main.bricksarea
+ score = self.main.score
+ if bricka.active_group != 0 and bricka.is_on_brickarea(event.x, event.y - self.main.canvas_height):
+ bricka.change_active_group(0)
+ t = bricka.is_on_brick(event.x, event.y - self.main.canvas_height) # drag seleted brick to bricks_area
+ if t != -1 and t != bricka.bricks_cnt:
+ t2 = bricka.brick_highlight
+ bricka.brick_highlight = t
+ if t2 != -1 and t2 != t:
+ bricka.draw_1_score(t2)
+ if t2 != t:
+ bricka.draw_1_score_b(t, self.main.score.drag, self.main.score.dcut)
+ elif bricka.brick_highlight != -1: # cursor leave bricks_area
+ t2 = bricka.brick_highlight
+ bricka.brick_highlight = -1
+ bricka.draw_1_score(t2)
+
+ if t != -1 and t != bricka.bricks_cnt:
+ if not (gx == self.start_drag_gx and gy == self.start_drag_gy):
+ self.move_selection(self.start_drag_gx, self.start_drag_gy, self.start_drag_gx, self.start_drag_gy)
+ (self.last_gx, self.last_gy) = (self.start_drag_gx, self.start_drag_gy)
+ else:
+ gx, gy = self.xy2gridxy(event.x, event.y)
+ if not (gx == self.last_gx and gy == self.last_gy):
+ self.move_selection(self.start_drag_gx, self.start_drag_gy, gx, gy)
+ (self.last_gx, self.last_gy) = (gx, gy)
+
+ else:
+ gx, gy = self.within_score(event.x, event.y)
+ out = False
+ if self.is_rec() and self.cursor_x != -1 and self.main.toolbar.toolsel == 2:
+ gx = self.cursor_x
+ if gx < 0 or gx >= self.ngrid_h or gy < 0 or gy >= self.ngrid_v:
+ out = True
+ if (self.dblclick_state == 1 or self.dblclick_state == 3) and (self.start_drag_gx != gx or self.start_drag_gy != gy):
+ self.dblclick_state = 0
+ if not (gx == self.last_gx and gy == self.last_gy) and not out:
+ toolbar = self.main.toolbar
+ if toolbar.toolsel == -1 and toolbar.pstate != 0 or toolbar.toolsel == 0 and toolbar.fstate != 0:
+ self.draw_grid_cursor(widget, gx, gy, 1)
+ else:
+ self.draw_grid_cursor(widget, gx, gy, self.main.toolbar.toolsel)
+ (self.last_gx, self.last_gy) = (gx, gy)
+ t = self.is_on_button(event.x, event.y)
+ if t != self.button_highlight and (self.button_highlight != -1 or t != -1):
+# t2 = self.button_highlight
+ self.button_highlight = t
+ cr = self.pixmap.cairo_create()
+ widget = self.widget
+ self.draw_buttons(cr)
+ widget.window.draw_drawable(widget.get_style().fg_gc[gtk.STATE_NORMAL], self.pixmap, 0, 0, 0, 0, self.cx, self.height)
+ return True
+
+ # =====================================================================================================================================================
+
+ def is_on_button(self, x, y):
+ if x < 12 or x >= self.cx - 12:
+ return -1
+ for i in range(7):
+ if y >= self.cy + i*self.btn_h and y < self.cy + i*self.btn_h + self.btn_h - 8:
+ return i
+ return -1
+
+ def draw_buttons(self, cr):
+ cr.set_font_size(18)
+ for i in range(len(self.btns)):
+ (x0, y0) = (12, self.cy + i * self.btn_h)
+ (x1, y1) = (self.cx-12, self.cy + i * self.btn_h + self.btn_h - 8)
+ self.main.bricksarea.draw_curvy_rectangle(cr, x0, y0, x1, y1, 4, (self.button_highlight == i))
+ xb, yb, wid, hei = cr.text_extents(self.btns[i])[:4]
+ cr.set_source_rgb(0.4, 0.4, 0.4)
+ cr.move_to( (x0+x1)/2 - wid/2 - xb, (y0+y1)/2 - hei/2 - yb)
+ cr.show_text(self.btns[i])
+
+ def move_selection(self, sx, sy, gx, gy):
+ dx = gx - sx
+ dy = gy - sy
+ score = self.main.score
+ score.copy_drag_2_sel(dx, dy)
+ self.update_top()
+ return
+
+ def is_cursor_on_selection(self, gx, gy):
+ for i in range(8):
+ if self.main.score.sel[i][gx][gy] != 0:
+ return True
+ return False
+
+ def draw_deselection(self):
+# print "draw_deselection"
+ cr = self.pixmap.cairo_create()
+ score = self.main.score
+ self.draw_note_buf = list()
+ for i in range(self.ngrid_h):
+ for j in range(self.ngrid_v):
+ f = 0
+ for k in range(8):
+ if score.bsel[k][i][j] != 0: # finish de-selection
+ f = 1
+ if f == 1:
+ self.draw_grid(self.widget, cr, i, j, score.top[i][j], 0, 1)
+ self.execute_draw_buf(cr)
+ self.widget.window.draw_drawable(self.widget.get_style().fg_gc[gtk.STATE_NORMAL], self.pixmap, 0, 0, 0, 0, self.width, self.height)
+
+ def max(self, a, b):
+ if a > b:
+ return a
+ return b
+
+ def select_all(self):
+ score = self.main.score
+ flag = 0
+ for i in range(self.ngrid_h):
+ for j in range(self.ngrid_v):
+ for k in range(8): # de-selection
+ if score.sel[k][i][j] != 0:
+ score.map[k][i][j] = max(score.map[k][i][j], score.sel[k][i][j])
+ score.cut[k][i][j] = score.scut[k][i][j]
+ score.sel[k][i][j] = 0
+ score.scut[k][i][j] = 0
+
+ for i in range(self.ngrid_h): #select-all
+ for j in range(self.ngrid_v):
+ for k in range(8):
+ if score.map[k][i][j] != 0:
+ score.sel[k][i][j] = score.map[k][i][j]
+ score.scut[k][i][j] = score.cut[k][i][j]
+ score.map[k][i][j] = 0
+ score.cut[k][i][j] = 0
+ flag = 1
+ if flag == 1:
+# print "re_draw"
+ score.select_state = 1
+ cr = self.pixmap.cairo_create()
+ self.draw_score(cr)
+ self.widget.window.draw_drawable(self.widget.get_style().fg_gc[gtk.STATE_NORMAL], self.pixmap, 0, 0, 0, 0, self.width, self.height)
+
+ def do_select_same_color(self, widget, cr, sx, sy):
+ score = self.main.score
+ t = score.top[sx][sy]
+ if t == -1:
+ return
+ flag = 0
+ for i in range(self.ngrid_h):
+ for j in range(self.ngrid_v):
+ if score.map[t][i][j] != 0:
+ flag = 1
+ score.sel[t][i][j] = score.map[t][i][j]
+ score.scut[t][i][j] = score.cut[t][i][j]
+ score.map[t][i][j] = 0
+ score.cut[t][i][j] = 0
+ for i in range(self.ngrid_h):
+ for j in range(self.ngrid_v):
+ if score.sel[t][i][j] != 0 and (i == 0 or score.sel[t][i-1][j] == 0 or score.scut[t][i-1][j] == 1):
+ self.draw_selected_grid(widget, cr, i, j, t)
+ if flag == 1:
+ score.select_state = 1
+
+ def do_select_region(self, sx, sy, gx, gy, release = 0):
+ if sx == -1 or gy == -1: # if cursor is out of bound, return
+ return
+ (sx, sy, gx, gy) = self.switch_order(sx, sy, gx, gy)
+ score = self.main.score
+
+ flag = 0
+ if release == 1: # move region from map to sel
+ for i in range(gx-sx+1):
+ for j in range(gy-sy+1):
+ for k in range(8): # to do: select specific color
+ if score.map[k][sx+i][sy+j] != 0 and (sx+i == 0 or score.map[k][sx+i-1][sy+j] == 0 or score.cut[k][sx+i-1][sy+j] == 1):
+ len = 1
+ while score.cut[k][sx+i+len-1][sy+j] == 0 and (sx+i+len) < score.ngrid_h and score.map[k][sx+i+len][sy+j] != 0:
+ len = len + 1
+ if sx+i+len-1 <= gx:
+ flag = 1
+ for l in range(len):
+ score.sel[k][sx+i+l][sy+j] = score.map[k][sx+i+l][sy+j]
+ score.scut[k][sx+i+l][sy+j] = score.cut[k][sx+i+l][sy+j]
+ score.map[k][sx+i+l][sy+j] = 0
+ score.cut[k][sx+i+l][sy+j] = 0
+ if flag == 1:
+ score.select_state = 1
+
+ def adjust_volume_in_selected_region(self, sx, sy, gx, gy, mode): # 0: p 1: f 2: dim 3: cresc
+ if sx == -1 or gy == -1: # if cursor is out of bound, return
+ return
+ (sx, sy, gx, gy) = self.switch_order(sx, sy, gx, gy)
+ score = self.main.score
+
+ lx = -1
+ cnt = 0
+ for i in range(gx-sx+1):
+ for j in range(gy-sy+1):
+ for k in range(8):
+ if score.map[k][sx+i][sy+j] != 0 and (sx+i == 0 or score.map[k][sx+i-1][sy+j] == 0 or score.cut[k][sx+i-1][sy+j] == 1):
+ if lx != i:
+ lx = i
+ cnt = cnt + 1 # count how many note are there in the area (notes play at the same time will be counted once only)
+ lx = -1
+ cnt2 = 0
+ if cnt == 0:
+ return
+ cr = self.pixmap.cairo_create()
+ widget = self.widget
+ for i in range(gx-sx+1):
+ for j in range(gy-sy+1):
+ f = 0
+ for k in range(8):
+ if score.map[k][sx+i][sy+j] != 0 and (sx+i == 0 or score.map[k][sx+i-1][sy+j] == 0 or score.cut[k][sx+i-1][sy+j] == 1):
+ f = 1
+ if lx != i:
+ lx = i
+ cnt2 = cnt2 + 1 # count how many note are there in the area (notes play at the same time will be counted once only)
+ if mode == 0:
+ score.map[k][sx+i][sy+j] = score.map[k][sx+i][sy+j] * 0.88
+ elif mode == 1:
+ score.map[k][sx+i][sy+j] = score.map[k][sx+i][sy+j] * 1.15
+ elif mode == 2:
+ score.map[k][sx+i][sy+j] = score.map[k][sx+i][sy+j] * (1.0 - 0.3 * (cnt2-1) / (cnt-1))
+ elif mode == 3:
+ score.map[k][sx+i][sy+j] = score.map[k][sx+i][sy+j] * (1.0 + 0.4 * (cnt2-1) / (cnt-1))
+ if score.map[k][sx+i][sy+j] >= 3:
+ score.map[k][sx+i][sy+j] = 3
+ elif score.map[k][sx+i][sy+j] <= 0.2:
+ score.map[k][sx+i][sy+j] = 0.2
+ if f == 1:
+ c = score.top[sx+i][sy+j]
+ self.draw_grid(widget, cr, sx+i, sy+j, c, 0)
+ widget.window.draw_drawable(widget.get_style().fg_gc[gtk.STATE_NORMAL], self.pixmap, 0, 0, 0, 0, self.width, self.height)
+
+ def get_first_color(self, gx, gy):
+ c = self.main.toolbar.colorsel
+ if self.main.score.map[c][gx][gy] != 0 or self.main.score.sel[c][gx][gy] != 0:
+ return c
+ for i in range(8):
+ if self.main.score.map[i][gx][gy] != 0 or self.main.score.sel[i][gx][gy] != 0:
+ return i
+ return -1
+
+ def get_top_color_detail(self, gx, gy, sel):
+ c = self.main.toolbar.colorsel
+
+ if sel[c][gx][gy] != 0:
+ return (c, 1)
+ elif self.main.score.map[c][gx][gy] != 0:
+ return (c, 0)
+ for i in range(8):
+ if sel[i][gx][gy] != 0:
+ return (i, 1)
+ elif self.main.score.map[i][gx][gy] != 0:
+ return (i, 0)
+
+ return (-1, -1)
+
+ def update_top(self):
+ score = self.main.score
+ #score.top_buf = copy(score.top)
+ for i in range(self.ngrid_h):
+ for j in range(self.ngrid_v):
+ score.top_buf[i][j] = score.top[i][j]
+ score.top[i][j] = self.get_first_color(i, j)
+
+ for i in range(self.ngrid_h):
+ for j in range(self.ngrid_v):
+ if score.top_buf[i][j] != score.top[i][j] and score.top[i][j] == -1:
+ if i!=0 and score.top[i-1][j] != -1 and score.top_buf[i-1][j] == score.top[i-1][j]:
+ score.top_buf[i-1][j] = -99 # force redraw
+ if _showGraphcisEvent:
+ print "force redraw (%d,%d)" % (i-1,j)
+ if i+1 < self.ngrid_h and score.top[i+1][j] != -1 and score.top_buf[i+1][j] == score.top[i+1][j]:
+ score.top_buf[i+1][j] = -99
+ if _showGraphcisEvent:
+ print "force redraw (%d,%d)" % (i+1,j)
+ if score.top[i][j] != -1 and score.top_buf[i][j] == score.top[i][j]:
+ (c_A, is_sel_A) = self.get_top_color_detail(i, j, score.bsel)
+ (c_B, is_sel_B) = self.get_top_color_detail(i, j, score.sel)
+ if _showGraphcisEvent:
+ print "top_color detail -> %d,%d %d,%d" % (c_A, is_sel_A, c_B, is_sel_B)
+ if not (is_sel_A == is_sel_B and c_A == c_B):
+ score.top_buf[i][j] = -99
+ if _showGraphcisEvent:
+ print "force redraw (%d,%d)" % (i,j)
+# if score.
+ cr = self.pixmap.cairo_create()
+ widget = self.widget
+
+ #for i in range(self.ngrid_h):
+ #for j in range(self.ngrid_v):
+ #if score.top[i][j] != score.top_buf[i][j]:
+ #self.clean_cursor_mode(cr, i, j)
+ self.umask = self.zeros(self.ngrid_h, self.ngrid_v)
+ self.draw_note_buf = list()
+ c = self.get_rev_color_list()
+ c.insert(0, -1)
+ sx = sy = ex = ey = -1
+# print c
+ for k in range(len(c)):
+ for i in range(self.ngrid_h):
+ for j in range(self.ngrid_v):
+ if score.top[i][j] != score.top_buf[i][j]:
+ if sx == -1 or i < sx: # maintain a minimum region (sx,sy)-(ex,ey) to be updated
+ sx = i
+ if ex == -1 or i > ex:
+ ex = i
+ if sy == -1 or j < sy:
+ sy = j
+ if ey == -1 or j > ey:
+ ey = j
+ if self.main.score.top[i][j] == c[k]:
+# print "draw (%d,%d,%d)"%(i,j,c[k])
+ if c[k] == -1:
+ self.clear_note(cr, i, j, 1, 0, 1)
+ else:
+ self.draw_grid(widget, cr, i, j, score.top[i][j], (score.sel[c[k]][i][j] != 0), 1) # draw_note buffer mode
+ self.execute_draw_buf(cr)
+
+ #self.draw_canvas(cr)
+ #self.draw_score(cr)
+
+ widget.window.draw_drawable(widget.get_style().fg_gc[gtk.STATE_NORMAL], self.pixmap, self.cx+sx*self.gridw-1, self.cy+sy*self.gridh, self.cx+sx*self.gridw-1, self.cy+sy*self.gridh, (ex-sx+1)*self.gridw+2, (ey-sy+1)*self.gridh)
+ #widget.window.draw_drawable(widget.get_style().fg_gc[gtk.STATE_NORMAL], self.pixmap, 0, 0, 0, 0, self.width, self.height)
+
+ def update_top_all(self):
+ for i in range(self.ngrid_h):
+ for j in range(self.ngrid_v):
+ self.main.score.top[i][j] = self.get_first_color(i, j)
+ cr = self.pixmap.cairo_create()
+ self.draw_canvas(cr)
+ self.draw_score(cr)
+ widget = self.widget
+ widget.window.draw_drawable(widget.get_style().fg_gc[gtk.STATE_NORMAL], self.pixmap, 0, 0, 0, 0, self.width, self.height)
+
+ def highlight_grid(self, erase_mode = False):
+ if self.main.score.play_state != -1:
+ return
+
+ cr = self.pixmap.cairo_create()
+ fa = False
+ fb = False
+ gx = (int)((self.main.score.currentTime - self.main.score.startSessionTime + self.main.score.score_start_time) / self.main.score.grid_tdiv)
+ self.cursor_x = gx
+ if (not erase_mode) and self.last_hgx == gx:
+ return
+ if gx < 0:
+ return
+ elif gx >= self.ngrid_h and not erase_mode:
+ self.highlight_grid(True)
+ self.last_hgx = -1
+ if self.main.toolbar.loop == 0:
+ self.main.score.play_state = -2
+ self.main.toolbar.update()
+ else:
+ self.main.score.play_music(self.main.csound)
+# print "stop"
+ return
+ self.last_hgx = gx
+ if gx != 0 and gx-1 < self.ngrid_h:
+ fa = True
+ if gx < self.ngrid_h:
+ fb = True
+ if not fa and not fb:
+ if erase_mode:
+ return
+ self.last_hgx = -1
+ if self.main.toolbar.loop == 0:
+ self.main.score.play_state = -2
+ self.main.toolbar.update()
+ else:
+ self.main.score.play_music(self.main.csound)
+ return
+
+ for j in range(self.ngrid_v):
+# original code, commented out by wuhsi, 03/03/2010
+# if fa and self.main.score.top[gx-1][j] != -1 and (self.main.score.select_state == 0 or self.main.score.sel[self.main.score.top[gx-1][j]][gx-1][j] != 0):
+# self.draw_grid(self.widget, cr, gx-1, j, self.main.score.top[gx-1][j])
+# if fb and self.main.score.top[gx][j] != -1 and (self.main.score.select_state == 0 or self.main.score.sel[self.main.score.top[gx][j]][gx][j] != 0):
+# if erase_mode:
+# self.draw_grid(self.widget, cr, gx, j, self.main.score.top[gx][j])
+# else:
+# self.draw_grid(self.widget, cr, gx, j, -1)
+ if fa:
+ if self.main.score.top[gx-1][j] != -1:
+ self.draw_grid(self.widget, cr, gx-1, j, self.main.score.top[gx-1][j])
+ else:
+ self.clear_note(cr, gx-1, j, 1)
+ if fb:
+ if erase_mode:
+ if self.main.score.top[gx][j] != -1:
+ self.draw_grid(self.widget, cr, gx, j, self.main.score.top[gx][j])
+ else:
+ self.clear_note(cr, gx, j, 1)
+ else:
+ self.draw_grid(self.widget, cr, gx, j, -1)
+
+
+ sy = 0
+ ey = self.ngrid_v-1
+ if fa and fb:
+ sx = gx-1
+ ex = gx
+ elif fa:
+ sx = gx-1
+ ex = gx-1
+ elif fb:
+ sx = gx
+ ex = gx
+ self.widget.window.draw_drawable(self.widget.get_style().fg_gc[gtk.STATE_NORMAL], self.pixmap, self.cx+sx*self.gridw-1, self.cy+sy*self.gridh, self.cx+sx*self.gridw-1, self.cy+sy*self.gridh, (ex-sx+1)*self.gridw+2, (ey-sy+1)*self.gridh)
+# self.widget.window.draw_drawable(self.widget.get_style().fg_gc[gtk.STATE_NORMAL], self.pixmap, 0, 0, 0, 0, self.width, self.height)
+
+# print "score time = %.2f, score_end_time = %.2f" % (self.main.score.currentTime - self.main.score.startSessionTime, self.main.score.score_end_time)
+
+ if not self.main.toolbar.from_start and not erase_mode and (self.main.score.currentTime - self.main.score.startSessionTime) > self.main.score.score_end_time:
+# print "call highlight_grid erase mode"
+ self.highlight_grid(True)
+ if self.main.toolbar.loop == 0:
+ self.main.score.play_state = -2
+ self.main.toolbar.update()
+ else:
+ self.main.score.play_music(self.main.csound)
+ return
+
+ if gx < 0 or gx >= self.ngrid_h:
+ return
+ if self.rec_gx != -1 and self.rec_gy != -1: # writing notes in metro mode
+ if gx != self.rec_gx and self.main.toolbar.colorsel != 7:
+ self.draw_cell(self.widget, gx, self.rec_gy, True)
+ self.rec_gx = gx
+ elif self.is_rec() and self.last_gy != -1 and self.main.toolbar.toolsel == 2 and gx != self.last_gx:
+ self.draw_grid_cursor(self.widget, gx, self.last_gy, self.main.toolbar.toolsel)
+ self.last_gx = gx
+
+ if self.is_rec() and self.last_gx_key != gx: # on timeline moved, write note if keyboard is pressed
+ if self.main.toolbar.colorsel != 7:
+ for i in range(self.ngrid_v):
+ if self.main.score.keyon[i] != 0:
+ self.paint_cell(self.widget, gx, i)
+ self.last_gx_key = gx
+
+ def write_note_keyboard(self, gy):
+ if self.is_rec():
+ self.paint_cell(self.widget, self.last_gx_key, gy)
+
+ def clear_note(self, cr, gx, gy, len, erase = 0, buf = 0): # given a cairo_context and the location of note, draw the area with white / bg color
+ if buf == 1:
+ self.draw_note_buf.append([gx,gy,len,1,erase,-1,-1])
+ return
+ if _showGraphcisEvent:
+ print "clean (%d, %d, %d)" % (gx, gy, len)
+ x0, y0 = self.cx+gx*self.gridw, self.cy+gy*self.gridh+2
+ x1, y1 = x0+self.gridw*len, y0+self.gridh-4
+
+ gradient_change = self.set_gradient(self.set_cycle(),self.set_offset(),self.ngrid_v-gy-1)
+
+ if erase == 1:
+ cr.set_source_rgba(1, 1, 1, 0.7)
+ cr.rectangle(x0, y0, x1-x0, y1-y0)
+ else:
+ #cr.set_source_rgb(0.93, 0.86, 0.72)
+ cr.set_source_rgb(1.0-gradient_change, 0.95-gradient_change, 0.80-gradient_change)
+ cr.rectangle(x0-1, y0-1, x1-x0+2, y1-y0+2)
+ cr.fill()
+
+ def draw_note(self, cr, gx, gy, len, c, v, sel = 0, buf = 0): # given a cairo_context and the location of note, draw the note (frame and color)
+ if buf == 1:
+ self.draw_note_buf.append([gx,gy,len,0,c,sel,v])
+ return
+ if _showGraphcisEvent:
+ print "draw (%d, %d, %d) sel = %d" % (gx, gy, len, sel)
+ x0, y0 = self.cx+gx*self.gridw, self.cy+gy*self.gridh+2
+ x1, y1 = x0+self.gridw*len, y0+self.gridh-4
+ r = self.gridw/2
+ for i in range(len):
+ self.umask[gx+i][gy] = 1
+
+ self.set_color(cr, c, v)
+# cr.set_source_color(self.color_list[c])
+ cr.move_to(x0, y0 + r)
+ cr.curve_to(x0, y0, x0, y0, x0+r, y0)
+ cr.line_to(x1-r, y0)
+ cr.curve_to(x1, y0, x1, y0, x1, y0+r)
+ cr.line_to(x1, y1-r)
+ cr.curve_to(x1, y1, x1, y1, x1-r, y1)
+ cr.line_to(x0+r, y1)
+ cr.curve_to(x0, y1, x0, y1, x0, y1-r)
+ cr.close_path()
+ cr.fill_preserve()
+ cr.set_line_width(1)
+ cr.set_source_rgb(0, 0, 0)
+ if sel == 1:
+ dashes = [6.0, 3.0]
+ cr.set_dash(dashes, 0.0)
+ else:
+ dashes = []
+ cr.set_dash(dashes, 0.0)
+ cr.stroke()
+
+ def erase_grid(self, widget, cr, gx, gy):
+ self.clear_note(cr, gx, gy, 1)
+ #widget.window.draw_drawable(widget.get_style().fg_gc[gtk.STATE_NORMAL], self.pixmap, 0, 0, 0, 0, self.width, self.height)
+
+ def clear_grid_cursor(self, widget, tsel):
+
+ gradient_change = self.set_gradient(self.set_cycle(),self.set_offset(),self.ngrid_v-self.last_gy-1)
+ cr = self.pixmap.cairo_create()
+ if self.last_gx != -1 and self.last_gy != -1:
+ if tsel != 4:
+ if self.main.score.top[self.last_gx][self.last_gy] == -1:
+ cr.set_source_rgb(1.0-gradient_change, 0.95-gradient_change, 0.80-gradient_change)
+ #cr.set_source_rgb(0.93, 0.86, 0.72)
+ cr.rectangle(self.cx+self.last_gx*self.gridw+1, self.cy+self.last_gy*self.gridh+2-1, self.gridw-2, self.gridh-4+2)
+ cr.fill()
+ else:
+ self.draw_grid(widget, cr, self.last_gx, self.last_gy, self.main.score.top[self.last_gx][self.last_gy])
+ widget.window.draw_drawable(widget.get_style().fg_gc[gtk.STATE_NORMAL], self.pixmap, 0, 0, 0, 0, self.width, self.height)
+
+ def clean_cursor_mode(self, cr, gx, gy):
+ # this has been added:
+
+ gradient_change = self.set_gradient(self.set_cycle(),self.set_offset(),self.ngrid_v-gy-1)
+
+ if gy >= self.ngrid_v:
+ return
+
+ if self.main.score.top[gx][gy] == -1:
+ #cr.set_source_rgb(0.93, 0.86, 0.72)
+ cr.set_source_rgb(1.0-gradient_change, 0.95-gradient_change, 0.80-gradient_change)
+ cr.rectangle(self.cx+gx*self.gridw, self.cy+gy*self.gridh+2-1, self.gridw, self.gridh-4+2)
+ cr.fill()
+ else:
+ self.draw_grid(self.widget, cr, gx, gy, self.main.score.top[gx][gy])
+
+ if self.is_rec() and gx == self.cursor_x:
+ self.draw_grid(self.widget, cr, gx, gy, -1)
+
+
+ def draw_cursor_white(self, cr, gx, gy):
+ cr.set_source_rgba(1, 1, 1, 0.6)
+ cr.rectangle(self.cx+gx*self.gridw, self.cy+gy*self.gridh+2-1, self.gridw, self.gridh-4+2)
+ cr.fill()
+
+ def draw_grid_cursor(self, widget, gx, gy, tsel):
+# print "(%d,%d) (%d,%d)" % (self.last_gx, self.last_gy, gx, gy)
+ x0, y0 = self.cx+gx*self.gridw, self.cy+gy*self.gridh+2
+ x1, y1 = x0+self.gridw, y0+self.gridh-4
+
+ lx = self.last_gx
+ ly = self.last_gy
+ sdx = self.start_drag_gx
+ sdy = self.start_drag_gy
+
+ cr = self.pixmap.cairo_create()
+ if self.last_gx != -1: # erase old cursor
+ if tsel == 2 or tsel == 3:
+ self.clean_cursor_mode(cr, self.last_gx, self.last_gy)
+ elif tsel == 4:
+ if self.main.score.top[self.last_gx][self.last_gy] != -1: # cut mode
+ self.draw_grid(widget, cr, self.last_gx, self.last_gy, self.main.score.top[self.last_gx][self.last_gy])
+# added by wuhsi 0303 2010
+ elif not (tsel == 1 and sdx != -1):
+ self.clean_cursor_mode(cr, self.last_gx, self.last_gy)
+# elif tsel == 1:
+# if self.start_drag_gx != -1:
+# self.clean_selection_frame(cr, self.start_drag_gx, self.start_drag_gy, self.last_gx, self.last_gy)
+
+ if gx != -1: # draw new cursor
+ if tsel == 4:
+ if gx+1 < self.ngrid_h and self.main.score.top[gx][gy] != -1 and self.main.score.top[gx][gy] == self.main.score.top[gx+1][gy]:
+ cr.set_source_rgb(0.2, 0.2, 0.2)
+ cr.rectangle(x1, y0-1, 2, y1-y0+2)
+ cr.fill()
+ elif tsel == 2 or tsel == 3:
+ if tsel == 3:
+ cr.set_source_rgba(1, 1, 1, 0.8)
+ else:
+ c1, c2, c3 = self.main.toolbar.get_color_attr(self.main.toolbar.colorsel)
+ cr.set_source_rgba(c1, c2, c3, 0.8)
+ cr.rectangle(x0+1, y0-1, x1-x0-2, y1-y0+2)
+ cr.fill()
+ elif tsel == 1 and sdx != -1:
+ self.draw_selection_frame(cr, sdx, sdy, gx, gy)
+ else:
+ cr.set_source_rgba(1, 1, 1, 0.8)
+ cr.rectangle(x0+1, y0-1, x1-x0-2, y1-y0+2)
+ cr.fill()
+ else:
+ self.mask_buf = self.zeros(self.ngrid_h, self.ngrid_v)
+ if tsel == 1 and sdx != -1:
+ self.draw_selection_dif(cr)
+
+ if tsel == 1 and self.start_drag_gx != -1: # sdx, sdy, lx, ly, gx, gy
+ self.union_and_update(widget, sdx, sdy, lx, ly, gx, gy)
+ else:
+ widget.window.draw_drawable(widget.get_style().fg_gc[gtk.STATE_NORMAL], self.pixmap, self.cx+lx*self.gridw, self.cy+ly*self.gridh, self.cx+lx*self.gridw, self.cy+ly*self.gridh, self.gridw+1, self.gridh)
+ widget.window.draw_drawable(widget.get_style().fg_gc[gtk.STATE_NORMAL], self.pixmap, self.cx+gx*self.gridw, self.cy+gy*self.gridh, self.cx+gx*self.gridw, self.cy+gy*self.gridh, self.gridw+1, self.gridh)
+
+ def min3(self, v1, v2, v3):
+ if v1 <= v2 and v1 != -1 or v2 == -1:
+ if v1 <= v3 or v3 == -1:
+ return v1
+ else:
+ return v3
+ else:
+ if v2 <= v3 and v3 == -1:
+ return v2
+ else:
+ return v3
+
+ def max3(self, v1, v2, v3):
+ if v1 >= v2:
+ if v1 >= v3:
+ return v1
+ else:
+ return v3
+ else:
+ if v2 >= v3:
+ return v2
+ else:
+ return v3
+
+ def union_and_update(self, widget, sdx, sdy, lx, ly, gx, gy):
+ sx = self.min3(sdx, lx, gx)
+ sy = self.min3(sdy, ly, gy)
+ ex = self.max3(sdx, lx, gx)
+ ey = self.max3(sdy, ly, gy)
+ #print "(%d,%d) (%d,%d)" %(sx,sy,ex,ey)
+ widget.window.draw_drawable(widget.get_style().fg_gc[gtk.STATE_NORMAL], self.pixmap, self.cx+sx*self.gridw, self.cy+sy*self.gridh, self.cx+sx*self.gridw, self.cy+sy*self.gridh, (ex-sx+1)*self.gridw+1, (ey-sy+1)*self.gridh)
+
+ def switch_order(self, sx, sy, gx, gy):
+ if gx < sx:
+ return self.switch_order(gx, sy, sx, gy)
+ if gy < sy:
+ return (sx, gy, gx, sy)
+ return (sx, sy, gx, gy)
+
+ def execute_draw_buf(self, cr):
+ buf = self.draw_note_buf
+ for i in range(len(buf)):
+ flag = 0
+ if _showGraphcisEvent:
+ print "(%d, %d, %d) %d %d %d %d?" %(buf[i][0], buf[i][1], buf[i][2], buf[i][3], buf[i][4], buf[i][5], buf[i][6])
+ for j in range(i):
+ if buf[i] == buf[j]:
+ flag = 1
+ if _showGraphcisEvent:
+ print "(%d, %d, %d) %d %d ignore" %(buf[i][0], buf[i][1], buf[i][2], buf[i][3], buf[i][4])
+ break
+ if flag == 0:
+ if buf[i][3] == 0:
+ self.draw_note(cr, buf[i][0], buf[i][1], buf[i][2], buf[i][4], buf[i][6], buf[i][5])
+ else:
+ self.clear_note(cr, buf[i][0], buf[i][1], buf[i][2], buf[i][4])
+
+ def get_rev_color_list(self):
+ colorlist = list()
+ c = self.main.toolbar.colorsel
+ for i in range(8):
+ if 7-i != c:
+ colorlist.append(7-i)
+ colorlist.append(c)
+ return colorlist
+
+ def draw_selection_dif(self, cr):
+ for i in range(self.ngrid_h):
+ for j in range(self.ngrid_v):
+ if self.mask[i][j] != self.mask_buf[i][j]:
+ if _showGraphcisEvent:
+ print "clean (%d,%d)"%(i,j)
+ self.clean_cursor_mode(cr, i, j)
+ self.umask = self.zeros(self.ngrid_h, self.ngrid_v)
+ self.draw_note_buf = list()
+ c = self.get_rev_color_list()
+ for k in range(len(c)):
+ for i in range(self.ngrid_h):
+ for j in range(self.ngrid_v):
+ if self.mask[i][j] != self.mask_buf[i][j]:
+ if self.main.score.top[i][j] == c[k]:
+ if _showGraphcisEvent:
+ print "draw (%d,%d,%d)"%(i,j,c[k])
+ self.draw_grid(self.widget, cr, i, j, self.main.score.top[i][j], (int) (self.mask_buf[i][j] / 2), 1) # draw_note buffer mode
+ self.execute_draw_buf(cr)
+
+ for i in range(self.ngrid_h):
+ for j in range(self.ngrid_v):
+ if self.mask_buf[i][j] % 2 == 1 and (self.mask[i][j] != self.mask_buf[i][j] or self.umask[i][j] == 1):
+ if _showGraphcisEvent:
+ print "draw white (%d,%d)"%(i,j)
+ self.draw_cursor_white(cr, i, j)
+ self.mask[i][j] = self.mask_buf[i][j]
+
+ def clean_selection_frame(self, cr, sx, sy, gx, gy):
+ if sx == -1 or gx == -1: # if cursor is out of bound, return
+ return
+ (sx, sy, gx, gy) = self.switch_order(sx, sy, gx, gy)
+
+# for i in range(gx-sx+1):
+# for j in range(gy-sy+1):
+# if self.main.score.top[sx+i][sy+j] != -1:
+# self.draw_grid(self.widget, cr, sx+i, sy+j, self.main.score.top[sx+i][sy+j])
+ for i in range(gx-sx+1):
+ self.clean_cursor_mode(cr, sx+i, sy)
+ if sy != gy:
+ self.clean_cursor_mode(cr, sx+i, gy)
+ for i in range(gy-sy-1):
+ self.clean_cursor_mode(cr, sx, sy+i+1)
+ if sx != gx:
+ self.clean_cursor_mode(cr, gx, sy+i+1)
+
+ def draw_selection_frame(self, cr, sx, sy, gx, gy):
+ if sx == -1 or gx == -1: # if cursor is out of bound, return
+ return
+ (sx, sy, gx, gy) = self.switch_order(sx, sy, gx, gy)
+ (self.tsx, self.tsy, self.tgx, self.tgy) = (sx, sy, gx, gy) #
+ self.mask_buf = self.zeros(self.ngrid_h, self.ngrid_v)
+
+ for i in range(gx-sx+1):
+ for j in range(gy-sy+1):
+ if self.main.score.top[sx+i][sy+j] != -1:
+ self.mask_buf[sx+i][sy+j] = 2
+# (self.tsx, self.tsy, self.tgx, self.tgy) = (sx, sy, gx, gy)
+# self.draw_grid(self.widget, cr, sx+i, sy+j, self.main.score.top[sx+i][sy+j], 1)
+ for i in range(gx-sx+1):
+ self.mask_buf[sx+i][sy] = self.mask_buf[sx+i][sy] + 1
+# self.draw_cursor_white(cr, sx+i, sy)
+ if sy != gy:
+ self.mask_buf[sx+i][gy] = self.mask_buf[sx+i][gy] + 1
+# self.draw_cursor_white(cr, sx+i, gy)
+ for i in range(gy-sy-1):
+ self.mask_buf[sx][sy+i+1] = self.mask_buf[sx][sy+i+1] + 1
+# self.draw_cursor_white(cr, sx, sy+i+1)
+ if sx != gx:
+ self.mask_buf[gx][sy+i+1] = self.mask_buf[gx][sy+i+1] + 1
+# self.draw_cursor_white(cr, gx, sy+i+1)
+
+ def draw_selected_grid(self, widget, cr, gx, gy, c, buf = 0):
+ if _showGraphcisEvent:
+ print "draw_selected_grid(%d,%d) c=%d" % (gx, gy, c)
+ a = b = 1
+ while gx-a >= 0 and self.main.score.sel[c][gx-a][gy] != 0 and self.main.score.scut[c][gx-a][gy] == 0:
+ a = a + 1
+ while gx+b < self.ngrid_h and self.main.score.sel[c][gx+b][gy] and self.main.score.scut[c][gx+b-1][gy] == 0:
+ b = b + 1
+ v = self.main.score.sel[c][gx-a+1][gy]
+ self.clear_note(cr, gx-a+1, gy, a+b-1, buf)
+ self.draw_note(cr, gx-a+1, gy, a+b-1, c, v, 1, buf)
+
+ for i in range(8):
+ if i == c:
+ continue
+ j = gx-a+1
+ while j < gx+b:
+ if self.main.score.top[j][gy] == i:
+ self.draw_grid(widget, cr, j, gy, i, buf)
+ d = 1
+ while j+d < self.ngrid_h and self.main.score.top[j+d][gy] == i:
+ d = d + 1
+ j = j + d
+ else:
+ j = j + 1
+
+ def draw_grid(self, widget, cr, gx, gy, c, sel = 0, buf = 0):
+ if _showGraphcisEvent:
+ print "draw_grid(%d,%d) c=%d, sel=%d" % (gx, gy, c, sel)
+ if c == -1:
+ self.clear_note(cr, gx, gy, 1, 1, buf)
+ return
+
+ a = b = 1
+ if self.main.score.map[c][gx][gy] != 0:
+ a = b = 1
+ while gx-a >= 0 and self.main.score.map[c][gx-a][gy] != 0 and self.main.score.cut[c][gx-a][gy] == 0:
+ a = a + 1
+ while gx+b < self.ngrid_h and self.main.score.map[c][gx+b][gy] and self.main.score.cut[c][gx+b-1][gy] == 0:
+ b = b + 1
+ self.clear_note(cr, gx-a+1, gy, a+b-1, 0, buf)
+
+ v = self.main.score.map[c][gx-a+1][gy]
+ if sel == 1 and self.tsx <= gx-a+1 and gx+b-1 <= self.tgx and self.tsy <= gy and gy <=self.tgy: # region_selection only
+ self.draw_note(cr, gx-a+1, gy, a+b-1, c, v, 1, buf)
+ else:
+ self.draw_note(cr, gx-a+1, gy, a+b-1, c, v, 0, buf)
+ (ta, tb) = a, b
+
+ if self.main.score.sel[c][gx][gy] != 0:
+ a = b = 1
+ while gx-a >= 0 and self.main.score.sel[c][gx-a][gy] != 0 and self.main.score.scut[c][gx-a][gy] == 0:
+ a = a + 1
+ while gx+b < self.ngrid_h and self.main.score.sel[c][gx+b][gy] and self.main.score.scut[c][gx+b-1][gy] == 0:
+ b = b + 1
+
+ v = self.main.score.sel[c][gx-a+1][gy]
+ self.clear_note(cr, gx-a+1, gy, a+b-1, buf)
+ self.draw_note(cr, gx-a+1, gy, a+b-1, c, v, 1, buf)
+ if ta > a:
+ a = ta
+ if tb > b:
+ b = tb
+
+ for i in range(8):
+ if i == c:
+ continue
+ j = gx-a+1
+ while j < gx+b:
+ if self.main.score.top[j][gy] == i:
+ self.draw_grid(widget, cr, j, gy, i, sel, buf)
+ d = 1
+ while j+d < self.ngrid_h and self.main.score.top[j+d][gy] == i:
+ d = d + 1
+ j = j + d
+ else:
+ j = j + 1
+
+# self.draw_selected_grid(widget, cr, gx, gy, c, buf)
+
+# widget.queue_draw_area(self.cx+(gx-a+1)*self.gridw-1, self.cy+gy*self.gridh-1, self.gridw*(a+b-1)+2, self.gridh+2)
+
+ def paint_cell(self, widget, gx, gy): # call by draw_cell, to add a cell, redraw the adjacent notes
+ c = self.main.toolbar.colorsel
+ if _showGraphcisEvent:
+ print "map[%d][%d][%d] = %d" % (c,gx,gy,1)
+ if self.main.score.map[c][gx][gy] == 0:
+ self.main.score.map[c][gx][gy] = 1
+ if gx < self.ngrid_h and c == 7 and self.main.score.map[c][gx][gy] != 0:
+ self.main.score.cut[c][gx][gy] = 1
+ else:
+ self.main.score.cut[c][gx][gy] = 0
+ if gx > 0 and c == 7 and self.main.score.map[c][gx-1][gy] != 0:
+ self.main.score.cut[c][gx-1][gy] = 1
+ if self.main.score.top[gx][gy] != self.get_first_color(gx, gy):
+ self.main.score.top[gx][gy] = self.get_first_color(gx, gy)
+ cr = self.pixmap.cairo_create()
+ self.draw_grid(widget, cr, gx, gy, self.main.toolbar.colorsel)
+ widget.window.draw_drawable(widget.get_style().fg_gc[gtk.STATE_NORMAL], self.pixmap, self.cx+gx*self.gridw, self.cy+gy*self.gridh, self.cx+gx*self.gridw, self.cy+gy*self.gridh, self.gridw+1, self.gridh)
+
+ def erase_cell(self, widget, gx, gy): # call by draw_cell, to erase a cell, redraw the adjacent notes
+ if _showGraphcisEvent:
+ print "top[%d][%d] = %d" % (gx, gy, self.main.score.top[gx][gy])
+ if self.main.score.top[gx][gy] != -1:
+ cr = self.pixmap.cairo_create()
+ t = self.main.score.top[gx][gy]
+ self.main.score.map[t][gx][gy] = 0
+ self.main.score.cut[t][gx][gy] = 0
+ self.main.score.top[gx][gy] = self.get_first_color(gx, gy)
+ if _showGraphcisEvent:
+ print "top[%d][%d] = %d" % (gx, gy, self.main.score.top[gx][gy])
+ if self.main.score.top[gx][gy] == -1:
+ self.erase_grid(widget, cr, gx, gy)
+ else:
+ self.draw_grid(widget, cr, gx, gy, self.main.score.top[gx][gy])
+ if gx-1 >= 0 and self.main.score.top[gx-1][gy] != -1:
+ self.draw_grid(widget, cr, gx-1, gy, self.main.score.top[gx-1][gy])
+ if gx+1 < self.ngrid_h and self.main.score.top[gx+1][gy] != -1:
+ self.draw_grid(widget, cr, gx+1, gy, self.main.score.top[gx+1][gy])
+ #widget.window.draw_drawable(widget.get_style().fg_gc[gtk.STATE_NORMAL], self.pixmap, self.cx+gx*self.gridw, self.cy+gy*self.gridh, self.cx+gx*self.gridw, self.cy+gy*self.gridh, self.gridw+1, self.gridh)
+
+ def cut_cell(self, widget, gx, gy):
+ if gx+1 < self.ngrid_h and self.main.score.top[gx][gy] != -1 and self.main.score.top[gx][gy] == self.main.score.top[gx+1][gy]:
+ cr = self.pixmap.cairo_create()
+ t = self.main.score.top[gx][gy]
+ self.main.score.cut[t][gx][gy] = (self.main.score.cut[t][gx][gy] + 1)%2
+ self.draw_grid(widget, cr, gx, gy, t)
+ self.draw_grid(widget, cr, gx+1, gy, t)
+ widget.window.draw_drawable(widget.get_style().fg_gc[gtk.STATE_NORMAL], self.pixmap, 0, 0, 0, 0, self.width, self.height)
+
+ def draw_cell(self, widget, gx, gy, force_write = False): # call by motion or button_press
+ if not self.main.score.is_edited:
+ self.main.score.is_edited = True
+ self.main.window.set_title("Music Painter - " + self.main.username + " *")
+ if self.main.toolbar.toolsel == 3:
+ self.erase_cell(widget, gx, gy)
+ elif self.main.toolbar.toolsel == 4:
+ self.cut_cell(widget, gx, gy)
+ elif self.main.toolbar.toolsel == 2:
+ if gx == self.last_drag_gx and gy == self.last_drag_gy: # condition stands when call by button_press
+ if not force_write and self.main.score.map[self.main.toolbar.colorsel][gx][gy] != 0: # start with an already painted grid
+ self.erase_cell(widget, gx, gy) # assume the user intent to clean it
+ self.just_clean = 1
+ else: # start with an unpainted grid
+ self.paint_cell(widget, gx, gy)
+ else: # call by button_motion
+ if self.just_clean == 1: # undo the assumption
+ self.just_clean = 0
+ self.paint_cell(widget, self.last_drag_gx, self.last_drag_gy)
+ self.paint_cell(widget, gx, gy)
+ self.main.score.drag_on(self.main.csound, self.main.toolbar.toolsel, self.main.toolbar.colorsel, gy) # make dragging sound
+
+ def draw_canvas_highlight(self, flag):
+ cr = self.pixmap.cairo_create()
+ widget = self.widget
+ if flag == 1:
+ cr.set_source_rgba(1, 1, 1, 0.4)
+ cr.rectangle(self.cx-1, self.cy+1, self.ngrid_h*self.gridw+2, self.ngrid_v*self.gridh-2)
+ cr.fill()
+ else:
+ self.draw_canvas(cr)
+ self.draw_score(cr)
+ self.draw_buttons(cr)
+ widget.window.draw_drawable(widget.get_style().fg_gc[gtk.STATE_NORMAL], self.pixmap, 0, 0, 0, 0, self.width, self.height)
+ '''
+ def draw_canvas(self, cr):
+ cr.set_source_rgb(0.84,0.84,1)
+ cr.rectangle(0, 0, self.width, self.height)
+ cr.fill()
+
+ cr.set_source_rgb(0.93, 0.86, 0.72)
+ cr.rectangle(self.cx, self.cy, self.ngrid_h*self.gridw, self.ngrid_v*self.gridh)
+ cr.fill()
+
+ cr.set_source_rgb(0, 0, 0)
+ cr.set_line_width(0.5)
+ cr.move_to(self.cx-2, self.cy)
+ cr.line_to(self.cx-2, self.cy + self.ngrid_v*self.gridh)
+ cr.move_to(self.cx + self.ngrid_h*self.gridw +2, self.cy)
+ cr.line_to(self.cx + self.ngrid_h*self.gridw +2, self.cy + self.ngrid_v*self.gridh)
+ for i in range(self.ngrid_v+1):
+ cr.move_to(self.cx-2, self.cy+i*self.gridh)
+ cr.line_to(self.cx+self.ngrid_h*self.gridw+2 , self.cy+i*self.gridh)
+ cr.stroke()
+ '''
+ # this draw_canvas has been replaced with:
+ def canvas_cycle(self, cycle, offset, cr):
+
+ x = 0
+ while x < self.ngrid_v:
+ gradient = self.set_gradient(cycle,offset,x)
+ cr.set_source_rgb(1.0-gradient, 0.95-gradient, 0.80-gradient) # canvas background color (changes)
+ cr.rectangle(self.cx, self.cy+(self.gridh*(self.ngrid_v-x-1)), self.ngrid_h*self.gridw, self.gridh)
+ x += 1.0
+ cr.fill()
+
+ def set_cycle(self):
+
+ cycle = [7, 7, 12, 5, 5, 6]
+ return cycle[self.main.score.scale_mode]
+
+ def set_offset(self):
+
+ offset = offset = [4, 4, 4, 4, 4, 6]
+ return offset[self.main.score.scale_mode]
+
+ def set_gradient(self, cycle, offset, row):
+
+ gradient = (row+1+cycle-offset)%(cycle)*.015
+ return gradient
+
+ def draw_canvas(self, cr):
+
+ cr.set_source_rgb(0.84,0.84,1)
+ cr.rectangle(0, 0, self.width, self.height)
+ cr.fill()
+
+ self.canvas_cycle(self.set_cycle(),self.set_offset(),cr)
+
+ cr.set_source_rgb(0, 0, 0) # canvas frame
+ cr.set_line_width(0.5)
+ cr.move_to(self.cx, self.cy)
+ cr.line_to(self.cx, self.cy + self.ngrid_v*self.gridh)
+ cr.move_to(self.cx + self.ngrid_h*self.gridw, self.cy)
+ cr.line_to(self.cx + self.ngrid_h*self.gridw, self.cy + self.ngrid_v*self.gridh)
+ for i in range(self.ngrid_v+1): # canvas horizontal grid line
+ cr.move_to(self.cx, self.cy+i*self.gridh)
+ cr.line_to(self.cx+self.ngrid_h*self.gridw, self.cy+i*self.gridh)
+ cr.stroke()
+
+ def draw_score_util(self, cr, map, cut, c, sel = 0):
+ for i in range(8):
+ if 7-i == c:
+ continue;
+ for j in range(self.ngrid_v):
+ for k in range(self.ngrid_h):
+ if map[7-i][k][j] != 0 and (k==0 or map[7-i][k-1][j] == 0 or cut[7-i][k-1][j] == 1):
+ len = 1
+ while cut[7-i][k+len-1][j] == 0 and k+len < self.ngrid_h and map[7-i][k+len][j] != 0:
+ len = len + 1
+ v = self.main.score.map[7-i][k][j]
+ self.clear_note(cr, k, j, len, 0)
+ self.draw_note(cr, k, j, len, 7-i, v, sel)
+ for j in range(self.ngrid_v):
+ for k in range(self.ngrid_h):
+ if map[c][k][j] != 0 and (k==0 or map[c][k-1][j] == 0 or cut[c][k-1][j] == 1):
+ len = 1
+ while cut[c][k+len-1][j] == 0 and k+len < self.ngrid_h and map[c][k+len][j] != 0:
+ len = len + 1
+ v = self.main.score.map[c][k][j]
+ self.clear_note(cr, k, j, len, 0)
+ self.draw_note(cr, k, j, len, c, v, sel)
+
+ def draw_score(self, cr): # redraw the entire score
+ self.draw_score_util(cr, self.main.score.map, self.main.score.cut, self.main.toolbar.colorsel)
+ if self.main.score.select_state != 0:
+ self.draw_score_util(cr, self.main.score.sel, self.main.score.scut, self.main.toolbar.colorsel, 1)
+
+ # determine if the input location is within the score_area
+ # if not, return (-1, -1)
+ # if so, return grid index (gx, gy)
+ def within_score(self, x, y):
+ if x < self.cx or y < self.cy or x >= self.cx+self.gridw*self.ngrid_h or y >= self.cy+self.gridh*self.ngrid_v:
+ return -1, -1
+ return self.xy2gridxy(x, y)
+
+ # call by within_score
+ # or call directly for drag_selection, accept (gx, gy) even out of canvas
+ # return grid index (gx, gy)
+ def xy2gridxy(self, x, y):
+ gx = (int)((x-self.cx)/self.gridw)
+ gy = (int)((y-self.cy)/self.gridh)
+ return gx, gy
+
+ def set_color(self, cr, color, volume):
+ v = [[1, 0.23, 0.23], #red
+ [1, 0.5, 0], #orange
+ [0.98, 0.99, 0.01], #yellow
+ [0.635, 0.97, 0.01], #grass
+ [0.15, 0.59, 0.07], #green
+ [0, 1, 1], #lblue
+ [0, 0.02, 0.88], #blue
+ [0.58, 0.155, 1]] #purple
+ if volume >= 1:
+ t = math.pow(volume, 0.25)
+ v1 = v[color][0] / t
+ v2 = v[color][1] / t
+ v3 = v[color][2] / t
+ else:
+ t = math.pow(volume, 1.35)
+ v1 = 1 + t*(v[color][0]-1)
+ v2 = 1 + t*(v[color][1]-1)
+ v3 = 1 + t*(v[color][2]-1)
+ cr.set_source_rgb(v1, v2, v3)
+
+ def adjust_volume(self, gx, gy, t):
+ v = -1
+ if t == 0:
+ r = 1.05
+ else:
+ r = 0.96
+ score = self.main.score
+ flag = 0
+ if score.top[gx][gy] != -1:
+ if score.select_state == 1:
+ for i in range(8):
+ if score.sel[i][gx][gy] != 0:
+ len = 1
+ while gx-len >= 0 and score.sel[i][gx-len][gy] != 0 and score.scut[i][gx-len][gy] == 0:
+ len = len + 1
+ score.sel[i][gx-len+1][gy] = score.sel[i][gx-len+1][gy] * r
+ flag = 2
+ if score.sel[i][gx-len+1][gy] >= 3:
+ score.sel[i][gx-len+1][gy] = 3
+ elif score.sel[i][gx-len+1][gy] <= 0.2:
+ score.sel[i][gx-len+1][gy] = 0.2
+ if v == -1:
+ v = score.sel[i][gx-len+1][gy]
+ else:
+ for i in range(8):
+ if score.map[i][gx][gy] != 0:
+ len = 1
+ while gx-len >= 0 and score.map[i][gx-len][gy] != 0 and score.cut[i][gx-len][gy] == 0:
+ len = len + 1
+ score.map[i][gx-len+1][gy] = score.map[i][gx-len+1][gy] * r
+ flag = 1
+ if score.map[i][gx-len+1][gy] >= 3:
+ score.map[i][gx-len+1][gy] = 3
+ elif score.map[i][gx-len+1][gy] <= 0.2:
+ score.map[i][gx-len+1][gy] = 0.2
+ if v == -1:
+ v = score.map[i][gx-len+1][gy]
+ if flag != 0:
+ cr = self.pixmap.cairo_create()
+ widget = self.widget
+ c = score.top[gx][gy]
+ self.draw_grid(widget, cr, gx, gy, c, (flag == 2))
+ widget.window.draw_drawable(widget.get_style().fg_gc[gtk.STATE_NORMAL], self.pixmap, 0, 0, 0, 0, self.width, self.height)
+ return v
diff --git a/CsoundAPI.py b/CsoundAPI.py
new file mode 100644
index 0000000..018950a
--- /dev/null
+++ b/CsoundAPI.py
@@ -0,0 +1,614 @@
+##################################################
+# CsoundAPI.py
+#
+# Jeremy Flores, flores1@mit.edu
+# last modified 01/29/08
+
+import socket
+import threading
+import select
+import os
+import thread
+#import curses
+from time import sleep
+
+from codes import * # where we store values for the message codes (i.e. CONNECTED=1, etc.)
+
+import gobject
+
+IO_MASKS = gobject.IO_IN | gobject.IO_PRI | gobject.IO_ERR | gobject.IO_HUP
+
+waiton_endflg = 0
+
+class CsoundAPI(threading.Thread):
+
+ def __init__(self, address='localhost', port=7000, is_gtk=True, timeout=5, error_callback = None):
+ super(CsoundAPI, self).__init__()
+ self._deactivate = False
+ self._is_gtk = is_gtk # if it's going to be used in PyGTK, set this to True. If used from a terminal, set to False (to specify the thread type)
+ self._error_callback = error_callback
+ if str(address) != address:
+ print "Error: address must be a string"
+ return False
+ if int(port) != port:
+ print "Error: port must be an integer value"
+ return False
+ self._address = address
+ self._port = port
+ self._message_queue = [] # an ordered list of messages that we expect and the corresponding callbacks that will handle them when they arrive
+
+# HOST = '18.85.18.29' # The remote host
+# PORT = 42000 # The same port as used by the server
+
+# self.scratchSock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+# self.scratchSock.connect((HOST, PORT))
+
+ self._connect(timeout)
+ self._waiton_endflg = 0
+
+ def _connect(self, timeout):
+ print "Connecting to Csound..."
+ self._socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+ self._socket.settimeout(timeout)
+ self._socket.connect( (self._address, self._port) )
+ self._isConnected = True
+ if self._is_gtk == True:
+ gobject.io_add_watch(self._socket, IO_MASKS, self.gtk_run) # this will monitor self._socket for inputs in a separate thread
+ else:
+ self.start() # this will call self.start() in a separate thread
+
+ def gtk_run(self, socket, condition):
+ data = ''
+ try:
+ data = socket.recv(8)
+ if data != None:
+ if len(data) != 0:
+ self._parseReceived(data)
+ else:
+ print "**Csound server failed... disconnecting1"
+ if self._error_callback != None:
+ if self._deactivate == False:
+ print "recover callback()"
+ self._error_callback()
+ else:
+ print "ignore recover callback()"
+ self._isConnected = False
+ socket.close()
+ else:
+ print "**Csound server failed... disconnecting2"
+ if self._error_callback != None:
+ if self._deactivate == False:
+ print "recover callback()"
+ self._error_callback()
+ else:
+ print "ignore recover callback()"
+ self._isConnected = False
+ socket.close()
+ except:
+ pass
+ return self._isConnected
+
+
+ def run(self):
+ data = ''
+ while self._isConnected == True:
+ try:
+ data = self._socket.recv(8)
+ if data != None:
+ if len(data) != 0:
+ self._parseReceived(data)
+ else:
+ print "**Csound server failed... disconnecting1"
+ self._isConnected = False
+ self._socket.close()
+ else:
+ print "**Csound server failed... disconnecting2"
+ self._isConnected = False
+ self._socket.close()
+ except:
+ pass
+
+ def _parseReceived(self, buffer):
+ recv_code = int(buffer[0:2])
+ size = int(buffer[3:8])
+
+ callback = self._error_callback # if we receive something from CS and our message queue doesn't know how to handle it, send the data to the error_callback fcn.
+
+ for message in self._message_queue: # for each message in our message queue
+ code = message[0] # look up the code for this particular message
+ if code == recv_code: # if the type received matches the code recorded in our message
+ callback = message[1] # redefine our callback from the default error_callback to the one recorded in our message
+ if code != BUFTIMER and code != P2TIMER and code != UL_BEAT: # if not registered
+ print code,callback
+ self._message_queue.remove(message) # delete the message from our queue
+ break # break the loop since we found the first message that corresponds to the received type
+
+ try:
+ data = self._socket.recv(size)
+# print 'Received data:',data
+
+ if data != None:
+ if callback != None: # if the callback has been registered
+ callback(data) # execute the function that callback points to, passing to it the information contained in data
+ if len(data) == 0:
+ print "**Csound server failed... disconnecting3"
+ self._isConnected = False
+ self._socket.close()
+ else:
+ print "**Csound server failed... disconnecting4"
+ self._isConnected = False
+ self._socket.close()
+ except:
+ pass
+
+ def newInstance(self):
+ self._sendString("%2d %5d" %(NEW_INST, 0))
+
+ def setOrcName(self, str):
+ self._sendString("%2d %5d" %(ORCFIL, len(str)))
+ self._sendString(str)
+
+ def setScoName(self, str):
+ self._sendString("%2d %5d" %(SCOFIL, len(str)))
+ self._sendString(str)
+
+ def setMidiName(self, str):
+ self._sendString("%2d %5d" %(MIDFIL, len(str)))
+ self._sendString(str)
+
+ def sendOrcStr(self, str):
+ self._sendString("%2d %5d" %(ORCSTR, len(str)))
+ self._sendString(str)
+
+ def sendScoStr(self, str):
+ self._sendString("%2d %5d" %(SCOSTR, len(str)))
+ self._sendString(str)
+
+ def setAlias(self, alias, val):
+ str_val = str(val)
+ self._sendString("%2d %5d" %(SET_ALIAS, len(alias)))
+ self._sendString(alias)
+ self._sendString("%2d" %(len(str_val)))
+ self._sendString(str_val)
+
+ def getAlias(self, str, callback):
+ self._sendString("%2d %5d" %(GET_ALIAS, len(str)))
+ self._sendString(str)
+ self._message_queue.append([GET_ALIAS, callback])
+
+ def setVolume(self, val):
+ str_val = str(val)
+ self._sendString("%2d %5d" %(SET_VOLUME, len(str_val)))
+ self._sendString(str_val)
+
+ def getVolume(self, callback):
+ self._sendString("%2d %5d" %(GET_VOLUME, 0))
+ self._message_queue.append([GET_VOLUME, callback])
+
+ def setMasterVolume(self, val):
+ str_val = str(val)
+ self._sendString("%2d %5d" %(SET_MAS_VOL, len(str_val)))
+ self._sendString(str_val)
+
+ def getMasterVolume(self, callback):
+ self._sendString("%2d %5d" %(GET_MAS_VOL, 0))
+ self._message_queue.append([GET_MAS_VOL, callback])
+
+ def setTempo(self, val):
+ str_val = str(val)
+ self._sendString("%2d %5d" %(SET_TEMPO, len(str_val)))
+ self._sendString(str_val)
+
+ def getTempo(self, callback):
+ self._sendString("%2d %5d" %(GET_TEMPO, 0))
+ self._message_queue.append([GET_TEMPO, callback])
+
+ def setMidiSpeed(self, val):
+ str_val = str(val)
+ self._sendString("%2d %5d" %(SET_MIDISPEED, len(str_val)))
+ self._sendString(str_val)
+
+ def getMidiSpeed(self, callback):
+ self._sendString("%2d %5d" %(GET_MIDISPEED, 0))
+ self._message_queue.append([GET_MIDISPEED, callback])
+
+ def setMsgLevel(self, val):
+ str_val = str(val)
+ self._sendString("%2d %5d" %(SET_MSGLEVEL, len(str_val)))
+ self._sendString(str_val)
+
+ def getMsgLevel(self, callback):
+ self._sendString("%2d %5d" %(GET_MSGLEVEL, 0))
+ self._message_queue.append([GET_MSGLEVEL, callback])
+
+ def setDisplays(self, val):
+ str_val = str(val)
+ self._sendString("%2d %5d" %(SET_DISPLAYS, len(str_val)))
+ self._sendString(str_val)
+
+ def setGraphics(self, val):
+ str_val = str(val)
+ self._sendString("%2d %5d" %(SET_GRAPHICS, len(str_val)))
+ self._sendString(str_val)
+
+ def sendBeat(self):
+ self._sendString("%2d %5d" %(BEAT_EVT, 0))
+
+ def sendLinevt(self, str):
+ self._sendString("%2d %5d" %(LINE_EVT, len(str)))
+ self._sendString(str)
+
+ def sendClearLines(self):
+ self._sendString("%2d %5d" %(CLR_LINES, 0))
+
+ def setUploadBeat(self, val, callback):
+ str_val = str(val)
+ self._sendString("%2d %5d" %(UL_BEAT, len(str_val)))
+ self._sendString(str_val)
+ self._message_queue.append([UL_BEAT, callback])
+
+
+
+
+ def sendSVOpen(self):
+ self._sendString("%2d %5d" %(SVOPEN, 0))
+
+ def setInsRemote(self, insno, IPadrs, instance):
+ str_val = str(insno)
+ self._sendString("%2d %5d" %(INSREMOTE, len(str_val)))
+ self._sendString(str_val)
+ self._sendString("%2d" %(len(IPadrs)))
+ self._sendString(IPadrs)
+ str_val = str(instance)
+ self._sendString("%2d" %(len(str_val)))
+ self._sendString(str_val)
+
+ def setInsGlobal(self, insno, IPadrs, instance):
+ str_val = str(insno)
+ self._sendString("%2d %5d" %(INSGLOBAL, len(str_val)))
+ self._sendString(str_val)
+ self._sendString("%2d" %(len(IPadrs)))
+ self._sendString(IPadrs)
+ str_val = str(instance)
+ self._sendString("%2d" %(len(str_val)))
+ self._sendString(str_val)
+
+ def setMidiRemote(self, chnum, IPadrs, instance):
+ str_val = str(chnum)
+ self._sendString("%2d %5d" %(MIDIREMOTE, len(str_val)))
+ self._sendString(str_val)
+ self._sendString("%2d" %(len(IPadrs)))
+ self._sendString(IPadrs)
+ str_val = str(instance)
+ self._sendString("%2d" %(len(str_val)))
+ self._sendString(str_val)
+
+ def setMidiGlobal(self, chnum, IPadrs, instance):
+ str_val = str(chnum)
+ self._sendString("%2d %5d" %(MIDIGLOBAL, len(str_val)))
+ self._sendString(str_val)
+ self._sendString("%2d" %(len(IPadrs)))
+ self._sendString(IPadrs)
+ str_val = str(instance)
+ self._sendString("%2d" %(len(str_val)))
+ self._sendString(str_val)
+
+ def setAudioRemoteSI(self, IPadrs):
+ self._sendString("%2d %5d" %(AUDREMOTE_SI, len(IPadrs)))
+ self._sendString(IPadrs)
+
+ def setAudioGlobalSI(self, IPadrs):
+ self._sendString("%2d %5d" %(AUDGLOBAL_SI, len(IPadrs)))
+ self._sendString(IPadrs)
+
+ def setAudioRemoteSO(self, IPadrs):
+ self._sendString("%2d %5d" %(AUDREMOTE_SO, len(IPadrs)))
+ self._sendString(IPadrs)
+
+ def setAudioGlobalSO(self, IPadrs):
+ self._sendString("%2d %5d" %(AUDGLOBAL_SO, len(IPadrs)))
+ self._sendString(IPadrs)
+
+ def setXtraScoreEvents(self, xtras):
+ str_val = str(xtras)
+ self._sendString("%2d %5d" %(XTRA_SCOREVT, len(str_val)))
+ self._sendString(str_val)
+
+ def setXtraMidiNoteOns(self, xtras):
+ str_val = str(xtras)
+ self._sendString("%2d %5d" %(XTRA_MIDINOTEON, len(str_val)))
+ self._sendString(str_val)
+
+ def setXtraMidiNoteOffs(self, xtras):
+ str_val = str(xtras)
+ self._sendString("%2d %5d" %(XTRA_MIDINOTEOFF, len(str_val)))
+ self._sendString(str_val)
+
+ def setXtraMidiEvents(self, xtras):
+ str_val = str(xtras)
+ self._sendString("%2d %5d" %(XTRA_MIDIEVT, len(str_val)))
+ self._sendString(str_val)
+
+ def setXtraMidiMessages(self, xtras):
+ str_val = str(xtras)
+ self._sendString("%2d %5d" %(XTRA_MIDIMSG, len(str_val)))
+ self._sendString(str_val)
+
+ def setXtraSysexMessages(self, xtras):
+ str_val = str(xtras)
+ self._sendString("%2d %5d" %(XTRA_SYSEXMSG, len(str_val)))
+ self._sendString(str_val)
+
+ def setXtraAudioBufsSI(self, xtras):
+ str_val = str(xtras)
+ self._sendString("%2d %5d" %(XTRA_AUDBUF_SI, len(str_val)))
+ self._sendString(str_val)
+
+ def setXtraAudioBufsSO(self, xtras):
+ str_val = str(xtras)
+ self._sendString("%2d %5d" %(XTRA_AUDBUF_SO, len(str_val)))
+ self._sendString(str_val)
+
+
+ def setNetStats(self, val1, val2):
+ str_val = str(val1)
+ self._sendString("%2d %5d" %(NET_STATS, len(str_val)))
+ self._sendString(str_val)
+ str_val = str(val2)
+ self._sendString("%2d" %(len(str_val)))
+ self._sendString(str_val)
+
+ def sendPrintStats(self, str):
+ self._sendString("%2d %5d" %(PRINT_STATS, len(str)))
+ self._sendString(str)
+
+
+ def setIOBufFrames(self, val):
+ str_val = str(val)
+ self._sendString("%2d %5d" %(IOBUFFRAMES, len(str_val)))
+ self._sendString(str_val)
+
+ def setBufTimer(self, val, callback):
+ str_val = str(val)
+ self._sendString("%2d %5d" %(BUFTIMER, len(str_val)))
+ self._sendString(str_val)
+ self._message_queue.append([BUFTIMER, callback])
+
+ def setP2Timer(self, val, callback):
+ str_val = str(val)
+ self._sendString("%2d %5d" %(P2TIMER, len(str_val)))
+ self._sendString(str_val)
+ self._message_queue.append([P2TIMER, callback])
+
+ def setOMaxLag(self, val):
+ str_val = str(val)
+ self._sendString("%2d %5d" %(OMAXLAGG, len(str_val)))
+ self._sendString(str_val)
+
+ def setInName(self, str):
+ self._sendString("%2d %5d" %(INNAME, len(str)))
+ self._sendString(str)
+
+ def setOutName(self, str):
+ self._sendString("%2d %5d" %(OUTNAME, len(str)))
+ self._sendString(str)
+
+ def setIntAudio(self):
+ self._sendString("%2d %5d" %(INTAUDIO, 0))
+
+ def sendPrep(self):
+ self._sendString("%2d %5d" %(PREP, 0))
+
+ def sendPlay(self):
+ self._sendString("%2d %5d" %(PLAY, 0))
+
+ def sendPlayForTime(self, val):
+ str_val = str(val)
+ self._sendString("%2d %5d" %(PLAY_FOR_TIME, len(str_val)))
+ self._sendString(str_val)
+
+ def sendPause(self):
+ self._sendString("%2d %5d" %(PAUSE, 0))
+
+ def sendResume(self):
+ self._sendString("%2d %5d" %(RESUME, 0))
+
+ def sendPlayAll(self):
+ self._sendString("%2d %5d" %(PLAYALL, 0))
+
+ def sendPlayAllForTime(self, val):
+ str_val = str(val)
+ self._sendString("%2d %5d" %(PLAYALL_FOR_TIME, len(str_val)))
+ self._sendString(str_val)
+
+ def sendPauseAll(self):
+ self._sendString("%2d %5d" %(PAUSEALL, 0))
+
+ def sendResumeAll(self):
+ self._sendString("%2d %5d" %(RESUMEALL, 0))
+
+ def sendDeactivateWithCallback(self, callback):
+ self._sendString("%2d %5d" %(DEACTIVATE, 0))
+ self._message_queue.append([DEACTIVATE, callback])
+
+ def sendDeactivate(self):
+ self._sendString("%2d %5d" %(DEACTIVATE, 0))
+
+ def sendReactivateWithCallback(self, callback):
+ self._sendString("%2d %5d" %(REACTIVATE, 0))
+ self._message_queue.append([REACTIVATE, callback])
+
+ def sendReactivate(self):
+ self._sendString("%2d %5d" %(REACTIVATE, 0))
+
+ def sendRewind(self):
+ self._sendString("%2d %5d" %(REWIND1, 0))
+
+ def sendRewindAll(self):
+ self._sendString("%2d %5d" %(REWINDALL, 0))
+
+ def sendFastFwdForTime(self, val):
+ str_val = str(val)
+ self._sendString("%2d %5d" %(FASTFWD_FOR_TIME, len(str_val)))
+ self._sendString(str_val)
+
+ def sendFastFwdToTime(self, val):
+ str_val = str(val)
+ self._sendString("%2d %5d" %(FASTFWD_TO_TIME, len(str_val)))
+ self._sendString(str_val)
+
+ def sendEcho(self, callback):
+ print "send Echo"
+ self._sendString("%2d %5d" %(ECHO, 0))
+ self._message_queue.append([ECHO, callback])
+ print "return, caller will wait for the echo-back"
+
+ def sendDestroyWithCallback(self, callback):
+ print "send Destroy with callback"
+ self._sendString("%2d %5d" %(RELEASE_INST, 0))
+ self._message_queue.append([RELEASE_INST, callback])
+ print "return, caller will wait for the callback"
+
+ def sendDestroy(self): # this releases the Cs instance
+ print "send Destroy"
+ self._sendString("%2d %5d" %(RELEASE_INST, 0))
+ self._message_queue.append([RELEASE_INST, release_inst_callback])
+ global release_inst_callback_flag
+ release_inst_callback_flag = 1
+ print "sendDestroy() waiting for callback"
+ while release_inst_callback_flag == 1:
+ sleep(1)
+ print "callback caught, exit sendDestroy"
+
+ def setP2Timer(self, val, callback):
+ str_val = str(val)
+ self._sendString("%2d %5d" %(P2TIMER, len(str_val)))
+ self._sendString(str_val)
+ self._message_queue.append([P2TIMER, callback])
+
+ def sendDisconnect(self): # this releases the CL struct & closes the socket
+ self._sendString("%2d %5d" %(CL_DISCONNECT, 0))
+
+ def serverCloseio(self): # just close the server current io
+ print "api.serverCloseio()"
+ self._sendString("%2d %5d" %(SV_CLOSEIO, 0))
+
+ def enterLineInputMode(self): #should be cleaned up to be threaded etc.
+ i = True
+ print "Line Input Mode"
+ print "type score lines, or type 'exit'"
+ while i:
+ strinput = raw_input("")
+ if (strinput == "exit"):
+ i = False
+ else:
+ self.sendLinevt(strinput);
+ print "end of Line Input mode"
+
+ def enterBeatInputMode(self): #should be cleaned up to be threaded etc.
+ stdscr = curses.initscr()
+# curses.start_color()
+ curses.noecho()
+ curses.cbreak()
+ stdscr.keypad(1)
+# curses.init_pair(1, curses.COLOR_RED, curses.COLOR_WHITE)
+# i = True
+# stdscr.addstr("Beat Input Mode\n", curses.color_pair(1))
+# stdscr.addstr("press any button to enter a beat,\n", curses.color_pair(1))
+# stdscr.addstr("or q to exit this mode\n", curses.color_pair(1))
+# stdscr.refresh()
+ while 1:
+ c = stdscr.getch()
+ if c == ord('q'):
+ break
+ else:
+ self.sendBeat();
+# stdscr.addstr("exited Beat Input mode\n", curses.color_pair(1))
+# stdscr.refresh()
+ curses.nocbreak(); stdscr.keypad(0); curses.echo()
+ curses.endwin()
+
+ def _sendString(self, string):
+ try:
+ self._socket.send(string)
+ except socket.error, e:
+ self._isConnected = False
+ self._socket.close()
+
+# def addScratchCallback(self, callback):
+# self.callback = callback
+
+ def close(self):
+ print "Disconnecting from Csound..."
+ self.sendDestroy() # this releases the CS object
+ if self._is_gtk == False:
+ self.sendDisconnect() # this closes the socket
+ self._isConnected = False
+ #should send a command to csound to shut down this socket
+ #self._socket.shutdown(SHUT_RDWR)
+ self._socket.close()
+
+ def waitonEnd(self):
+ self._sendString("%2d %5d" %(WAITON_END, 0))
+ self._message_queue.append([WAITON_END, endsignal])
+ global waiton_endflg
+ waiton_endflg = 1
+ print "setting waiton_endflg"
+ while waiton_endflg == 1:
+ sleep(3)
+ print "end signal caught, exit waitonEnd"
+
+ def serverShutdown(self): # release ALL structs, close ALL sockets & shutdown the Server
+ print "sending Server Shutdown"
+ self._sendString("%2d %5d" %(SV_SHUTDOWN, 0))
+# self._message_queue.append([SV_SHUTDOWN, "shutdown"])
+# self._message_queue.append([SV_SHUTDOWN, shutdownsignal])
+# global shutdown_endflg
+ self._isConnected = False
+ self._socket.close()
+
+ #should send a command to csound to shut down this socket
+# shutdown_endflg = 1
+# print "setting shutdown_endflg"
+# while shutdown_endflg == 1:
+# sleep(1)
+
+ def after_gtk_destroy(self):
+ print "CsoundAPI::after_gtk_destroy()"
+ self.sendDisconnect() # this closes the socket
+ self._isConnected = False
+ #should send a command to csound to shut down this socket
+ #self._socket.shutdown(SHUT_RDWR)
+ self._socket.close()
+
+ def mpClose(self):
+ print "CsoundAPI::mpClose()"
+ #self.sendDestroyWithCallback(self.destorysignal)
+ #3sleep(1)
+ #self.serverCloseio()
+ #sleep(1)
+ print "serverShutDown"
+ self.serverShutdown()
+ #self._isConnected = False
+ #self._socket.close()
+ #sleep(1)
+
+ def destorysignal(self):
+ print "got destroy callback"
+# self.serverShutdown()
+
+def release_inst_callback(self):
+ print "release inst callback received"
+ global release_inst_callback_flag
+ release_inst_callback_flag = 0
+
+def endsignal(self):
+ print "got endsignal"
+ print "clearing waiton_endflg"
+ global waiton_endflg
+ waiton_endflg = 0
+
+def shutdownsignal(self):
+ print "Cserver has shutdown"
+# global shutdown_endflg
+# shutdown_endflg = 0
diff --git a/CsoundXOAgent.py b/CsoundXOAgent.py
new file mode 100644
index 0000000..e5fca9d
--- /dev/null
+++ b/CsoundXOAgent.py
@@ -0,0 +1,140 @@
+import os
+import subprocess
+import CsoundAPI
+
+from time import sleep
+
+class CsoundXOAgent():
+
+ def __init__(self, host, rand, callback, platform):
+ self.random = rand
+ self.host = host
+ self.port = 7000
+ self.callback = callback
+ self.platform = platform
+
+ self.initialize(host, self.port, callback, platform)
+
+ def initialize(self, host, port, callback, platform):
+ self.status = 0
+
+ if not self.launchServer(port):
+ print "Error in launching server."
+ self.status = -1
+ return
+
+ if not self.loadOrc():
+ print "Error in reading orchestra or score file."
+ self.status = -2
+ return
+
+ if not self.connectCsound(port):
+ print "Error in connecting to csound server."
+ self.status = -3
+ return
+
+ if not self.runCsound(callback):
+ print "Error in setting up csound server."
+ self.status = -4
+ return
+
+ self.status = 1
+
+ def recover(self):
+ print "CsoundXOAgent::recover()"
+ if self.status != -1:
+ try:
+ self.server.kill()
+ except:
+ print "cannot kill server"
+ self.port = self.random.randint(7000, 10000)
+ self.initialize(self.host, self.port, self.callback, self.platform)
+ return (self.status == 1)
+
+ def launchServer(self, port):
+ print self.platform
+ try:
+ if self.platform == "sugar-xo" or self.platform == "linux":
+ self.server = subprocess.Popen(['./csoundxo',str(port)])
+ # self.server = subprocess.Popen('strace -o trace'+str(port)+'.txt ./csoundxo ' + str(port), shell=True)
+ else: # default - windows
+ self.server = subprocess.Popen("csnd.exe " + str(port))
+ except:
+ return False
+ return True
+
+ def deactivate(self):
+ self.api.sendDeactivate()
+
+ def reactivate(self):
+ self.api.sendReactivate()
+
+ def connectCsound(self, port):
+ try:
+ sleep(1)
+ print "connecting to Server at port " + str(port)
+ self.connect(self.host, port)
+ except:
+ return False
+ return True
+
+ def runCsound(self, callback):
+ self.setup(callback)
+ self.perform()
+ return True
+
+ def loadOrc(self):
+ try:
+ forc = open("mpainter.orc","r")
+ fsco = open("mpainter.sco","r")
+ self.orchestra = forc.read()
+ self.score = fsco.read()
+ forc.close()
+ fsco.close()
+ except:
+ return False
+ return True
+
+ def connect(self, address, port):
+ self.api = CsoundAPI.CsoundAPI(address, port, True, 5, self.recover)
+ sleep(1)
+
+ def setup(self, callback):
+ self.api.newInstance()
+ self.api.sendOrcStr(self.orchestra)
+ self.api.sendScoStr(self.score)
+ self.api.setDisplays(0)
+ self.api.setMsgLevel(3)
+ self.api.setIOBufFrames(1024)
+ self.api.setIntAudio()
+ self.api.sendPrep()
+ self.api.setP2Timer(0.06, callback)
+# self.api.enterBeatInputMode()
+
+ def perform(self):
+ self.api.sendPlay()
+
+ def sendClearLines(self):
+ if self.status == 1:
+ print "Clearing existing csound events..."
+ self.api.sendClearLines()
+
+ def sendLinevt(self, eventStr):
+ if self.status == 1:
+ self.api.sendLinevt(eventStr)
+
+ def current_kperiod(self):
+ if self.status == 1:
+ return self.api.current_kperiod()
+ else:
+ return -1
+
+ def close(self):
+ print "to Close Csoundxo"
+ if self.status == 1:
+ self.api.mpClose()
+ try:
+ self.server.kill()
+ except:
+ print "cannot kill server"
+ self.status = 0
diff --git a/MPScore.py b/MPScore.py
new file mode 100644
index 0000000..e0d0b0a
--- /dev/null
+++ b/MPScore.py
@@ -0,0 +1,780 @@
+import os
+
+from Brick import *
+from copy import deepcopy
+
+_showCSoundMsg = False
+_showDebugMsg = False
+
+class MPScore:
+ def minusone(self, n1, n2):
+ array = [[-1 for i in range(n2)] for j in range(n1)]
+ return array
+
+ def zeros(self, n1, n2):
+ array = [[0 for i in range(n2)] for j in range(n1)]
+ return array
+
+ def zeros3(self, n1, n2, n3):
+ array = [[[0 for i in range(n3)] for j in range(n2)] for k in range(n1)]
+ return array
+
+ def delete_selection(self):
+ w = self.ngrid_h
+ h = self.ngrid_v
+# self.bsel = deepcopy(self.sel)
+ self.sel = self.zeros3(8, w, h) # score region that is already selected (after mouse_release)
+ self.scut = self.zeros3(8, w, h) # score region (cut) that is already selected (after mouse_release)
+ self.select_state = 0 # 0: none 1: selected
+
+ def __init__(self, w, h, platform, mp):
+ self.main = mp
+ self.platform = platform
+
+ self.top = self.minusone(w, h)
+ self.top_buf = self.minusone(w, h)
+
+ self.keyon = [0 for i in range(h)]
+ self.map = self.zeros3(8, w, h)
+ self.cut = self.zeros3(8, w, h)
+ self.title = ""
+ self.description = ""
+ self.note = ""
+
+ self.wsize = 8
+ self.csize = 8
+ self.tesize = 12
+ self.tsize = 8
+ self.work_bricks = [Brick(w, h, platform, mp) for i in range(self.wsize)]
+ self.mymelody_bricks = [Brick(w, h, platform, mp) for i in range(self.csize)]
+ self.myrhythm_bricks = [Brick(w, h, platform, mp) for i in range(self.csize)]
+ self.scale_bricks = [Brick(w, h, platform, mp) for i in range(6)]
+ self.cmelody_bricks = [Brick(w, h, platform, mp) for i in range(self.csize)]
+ self.crhythm_bricks = [Brick(w, h, platform, mp) for i in range(self.csize)]
+ self.trash_bricks = [Brick(w, h, platform, mp) for i in range(self.tsize)]
+ self.temp_bricks = [Brick(w, h, platform, mp) for i in range(self.tesize)]
+
+ self.work_bricks_cnt = 6
+ self.mymelody_bricks_cnt = 0
+ self.myrhythm_bricks_cnt = 0
+ self.scale_bricks_cnt = 6
+ self.cmelody_bricks_cnt = 0
+ self.crhythm_bricks_cnt = 0
+ self.trash_bricks_cnt = 0
+ self.temp_bricks_cnt = 0
+
+ self.srv_brick_list = []
+ self.local_brick_list = []
+
+ self.bricks = self.work_bricks
+
+ self.sel = self.zeros3(8, w, h) # score region that is already selected (after mouse_release)
+ self.scut = self.zeros3(8, w, h) # score region (cut) that is already selected (after mouse_release)
+ self.select_state = 0 # 0: none 1: selected
+
+ self.bsel = self.zeros3(8, w, h) # score region that is already selected (after mouse_release) (backup)
+# self.bscut = self.zeros3(8, w, h) # score region (cut) that is already selected (after mouse_release) (backup)
+ self.drag = self.zeros3(8, w, h) # score region drag backup
+ self.dcut = self.zeros3(8, w, h) # score region (cut) drag backup
+
+ self.filename = ""
+ self.is_edited = False
+ self.save_working_brick = False
+
+ self.play_continue = -1
+ self.time_continue = 99999999
+ self.is_load_profile = 0
+ self.ngrid_h = w
+ self.ngrid_v = h
+ self.scale_mode = 0
+ self.key_shift = 0
+ self.last_note = -1
+ self.play_state = -2 # -2: stop -1~3: playing
+ self.grid_tdiv = 0.25
+
+ self.currentTime = 0 # to be set
+ self.scale_list = ["Major", "Minor", "Chromatic", "Chinese_Pentatonic", "Japanese_Pentatonic", "Blue_note"]
+
+ self.load_scale_bricks()
+ self.create_local_brick_list()
+
+# def convert_username(self, name):
+# return name.replace(" ","").replace("-","").replace("\"","")
+
+ def check_if_server_has_file(self, filename):
+ if self.main.ftp_status == 0:
+ return
+ l = len(self.srv_brick_list)
+ for i in range(l):
+ if self.srv_brick_list[i] == filename:
+ return
+ srv_filename = filename
+ try:
+ stream = open("myscore/" + filename, 'r')
+ msg = self.main.ftp.storlines("STOR " + srv_filename, stream)
+ print "ftp::STOR " + srv_filename + "....." + msg
+ stream.close()
+ except:
+ print "ftp error...."
+ self.main.ftp_status = 0
+
+ def load_collected_list(self):
+ size = len(self.local_brick_list)
+ for i in range(size):
+ n = self.local_brick_list[i].split("_")
+ l = len(n)
+ #n[l-1] -> filename n[l-3] -> type
+ if (int)(n[l-3]) == 0:
+ self.cmelody_bricks[self.cmelody_bricks_cnt].read_score(self.local_brick_list[i], self)
+ self.cmelody_bricks_cnt = self.cmelody_bricks_cnt + 1
+ elif (int)(n[l-3]) == 2:
+ self.crhythm_bricks[self.crhythm_bricks_cnt].read_score(self.local_brick_list[i], self)
+ self.crhythm_bricks_cnt = self.crhythm_bricks_cnt + 1
+ for i in range(self.crhythm_bricks_cnt):
+ print self.crhythm_bricks[i].filename
+ if self.main.bricksarea.active_group == 4 or self.main.bricksarea.active_group == 5:
+ self.main.bricksarea.draw_scores()
+
+ def toInt(self, line):
+ return (int)(line.replace("\n","").replace("\r",""))
+
+ def toFloat(self, line):
+ return (float)(line.replace("\n","").replace("\r",""))
+
+ def toStr(self, line):
+ return line.replace("\n","").replace("\r","")
+
+ def load_profile(self, username):
+ self.is_load_profile = 1
+ try:
+ stream = open("profile/" + username + ".txt", 'r')
+ except:
+ print username + "'s user profile doesn't exist."
+ return
+
+ self.work_bricks_cnt = self.toInt(stream.readline()) # work brick
+ for i in range(self.work_bricks_cnt):
+ line = self.toStr(stream.readline())
+ if line[0] != "-" and i < self.wsize:
+ self.work_bricks[i].read_score(line, self)
+ if self.work_bricks_cnt > self.wsize:
+ self.work_bricks_cnt = self.wsize
+ if self.work_bricks_cnt < 6:
+ self.work_bricks_cnt = 6
+
+ self.mymelody_bricks_cnt = self.toInt(stream.readline()) # mymelody brick
+ for i in range(self.mymelody_bricks_cnt):
+ line = self.toStr(stream.readline())
+ if i < self.csize:
+ self.mymelody_bricks[i].read_score(line, self)
+ if self.mymelody_bricks_cnt > self.csize:
+ self.mymelody_bricks_cnt = self.csize
+
+ self.myrhythm_bricks_cnt = self.toInt(stream.readline()) # myrhythm brick
+ for i in range(self.myrhythm_bricks_cnt):
+ line = self.toStr(stream.readline())
+ if i < self.csize:
+ self.myrhythm_bricks[i].read_score(line, self)
+ if self.myrhythm_bricks_cnt > self.csize:
+ self.myrhythm_bricks_cnt = self.csize
+
+ self.cmelody_bricks_cnt = self.toInt(stream.readline()) # mymelody brick
+ for i in range(self.cmelody_bricks_cnt):
+ line = self.toStr(stream.readline())
+ if i < self.csize:
+ self.cmelody_bricks[i].read_score(line, self)
+ if self.cmelody_bricks_cnt > self.csize:
+ self.cmelody_bricks_cnt = self.csize
+
+ self.crhythm_bricks_cnt = self.toInt(stream.readline()) # myrhythm brick
+ for i in range(self.crhythm_bricks_cnt):
+ line = self.toStr(stream.readline())
+ if i < self.csize:
+ self.crhythm_bricks[i].read_score(line, self)
+ if self.crhythm_bricks_cnt > self.csize:
+ self.crhythm_bricks_cnt = self.csize
+
+ stream.close()
+
+ def save_profile(self, username):
+ if self.is_load_profile == 0:
+ return
+
+ stream = open("musicpainter.config", 'w')
+ stream.writelines(username + "\n" + self.main.ip)
+ stream.close()
+
+ stream = open("profile/" + username + ".txt", 'w')
+ if self.save_working_brick == True:
+ stream.writelines(str(self.work_bricks_cnt) + "\n") # don't upload bricks in working area
+ for i in range(self.work_bricks_cnt):
+ if self.work_bricks[i].is_blank == 1:
+ stream.writelines("-\n")
+ else:
+ if self.work_bricks[i].filename == "":
+ self.work_bricks[i].write_score(self)
+ self.check_if_server_has_file(self.work_bricks[i].filename)
+ stream.writelines(self.work_bricks[i].filename + "\n")
+ else:
+ stream.writelines("0\n")
+ stream.writelines(str(self.mymelody_bricks_cnt) + "\n")
+ for i in range(self.mymelody_bricks_cnt):
+ if self.mymelody_bricks[i].filename == "":
+ self.mymelody_bricks[i].write_score(self)
+ self.check_if_server_has_file(self.mymelody_bricks[i].filename)
+ stream.writelines(self.mymelody_bricks[i].filename + "\n")
+ stream.writelines(str(self.myrhythm_bricks_cnt) + "\n")
+ for i in range(self.myrhythm_bricks_cnt):
+ if self.myrhythm_bricks[i].filename == "":
+ self.myrhythm_bricks[i].write_score(self)
+ self.check_if_server_has_file(self.myrhythm_bricks[i].filename)
+ stream.writelines(self.myrhythm_bricks[i].filename + "\n")
+ stream.writelines(str(self.cmelody_bricks_cnt) + "\n")
+ for i in range(self.cmelody_bricks_cnt):
+ if self.cmelody_bricks[i].filename == "":
+ self.cmelody_bricks[i].write_score(self)
+ stream.writelines(self.cmelody_bricks[i].filename + "\n")
+ stream.writelines(str(self.crhythm_bricks_cnt) + "\n")
+ for i in range(self.crhythm_bricks_cnt):
+ if self.crhythm_bricks[i].filename == "":
+ self.crhythm_bricks[i].write_score(self)
+ self.check_if_server_has_file(self.crhythm_bricks[i].filename)
+ stream.writelines(self.crhythm_bricks[i].filename + "\n")
+ stream.close()
+
+ def create_local_brick_list(self):
+ self.local_brick_list = os.listdir("myscore")
+ self.local_brick_list = filter(lambda name: name.endswith(".mpb") or name.endswith(".mps"), self.local_brick_list)
+
+ def load_scale_bricks(self):
+ list = os.listdir("myscore")
+ list = filter(lambda name: name.endswith(".scale"), list)
+ list.sort()
+ for i in range(len(list)):
+ filename = list[i]
+ self.scale_bricks[i].read_score(filename,self)
+ self.scale_bricks[i].brick_type = 1
+
+ def clear_score(self):
+ w = self.ngrid_h
+ h = self.ngrid_v
+ if self.play_state != -2:
+ self.stop_music(self.main.csound)
+ if self.select_state != 0:
+ self.delete_selection()
+ self.top = self.minusone(w, h)
+ self.map = self.zeros3(8, w, h)
+ self.cut = self.zeros3(8, w, h)
+
+ def max(self, a, b):
+ if a > b:
+ return a
+ return b
+
+ def copy_drag_2_sel(self, dx, dy):
+ self.bsel = deepcopy(self.sel)
+# self.bscut = copy(self.scut)
+ self.sel = self.zeros3(8, self.ngrid_h, self.ngrid_v) # score region that is already selected (after mouse_release)
+ self.scut = self.zeros3(8, self.ngrid_h, self.ngrid_v) # score region (cut) that is already selected (after mouse_release)
+ for k in range(8):
+ for i in range(self.ngrid_h):
+ nx = i + dx
+ if not (0 <= nx and nx < self.ngrid_h):
+ continue
+ for j in range(self.ngrid_v):
+ ny = j + dy
+ if not (0 <= ny and ny < self.ngrid_v):
+ continue
+ if self.drag[k][i][j] != 0:
+ self.sel[k][nx][ny] = self.drag[k][i][j]
+ self.scut[k][nx][ny] = self.dcut[k][i][j]
+
+ def de_selection(self):
+ if self.select_state == 0:
+ return
+ self.bsel = deepcopy(self.sel)
+ for k in range(8):
+ for i in range(self.ngrid_h):
+ for j in range(self.ngrid_v):
+ if self.sel[k][i][j] != 0:
+ self.map[k][i][j] = max(self.map[k][i][j], self.sel[k][i][j])
+ self.cut[k][i][j] = self.scut[k][i][j]
+# print "bsel = %d" % self.bsel[k][i][j]
+# self.bsel[k][i][j] = self.sel[k][i][j]
+ self.sel[k][i][j] = 0
+ self.scut[k][i][j] = 0
+ self.select_state = 0
+
+ def map_scale2(self, v, mode, shift):
+
+ major_scale = [0,2,4,5,7,9,10,12,14,16,17,19,21,22,24,26,28,29]
+ minor_scale = [0,1,4,5,7,8,10,12,13,16,17,19,20,22,24,25,28,29]
+ chromatic_scale = range(self.ngrid_v);
+ pentatonic_scale = [0, 3, 5, 8, 10, 12, 15, 17, 20, 22, 24, 27, 29, 32, 34, 36, 39, 41]
+ japanese_scale = [-7, -3, -1, 0, 4, 5, 9, 11, 12, 16, 17, 21, 23, 24, 28, 29, 33, 35, 36, 40, 41]
+ #blue_scale = [0, 1, 4, 6, 9, 11, 12, 13, 16, 18, 21, 23, 24, 25, 28, 30, 33, 35]
+# blue_scale = [-6, -5, -2, 0, 2, 3, 5, 6, 7, 10, 12, 14, 15, 17, 18, 19, 22, 24]
+ blue_scale = [0, 1, 4, 6, 9, 11, 12, 13, 16, 18, 21, 23, 24, 25, 28, 30, 33, 35]
+
+ if mode == 0:
+ return 55 + major_scale[self.ngrid_v-v-1] + shift;
+ elif mode == 1:
+ return 55 + minor_scale[self.ngrid_v-v-1] + shift;
+ elif mode == 2:
+ return 57 + chromatic_scale[self.ngrid_v-v-1] + shift;
+ elif mode == 3:
+ return 52 + pentatonic_scale[self.ngrid_v-v-1] + shift;
+ elif mode == 4:
+ return 60 + japanese_scale[self.ngrid_v-v-1] + shift;
+ elif mode == 5:
+ return 54 + blue_scale[self.ngrid_v-v-1] + shift - 5;
+# return 60 + blue_scale[self.ngrid_v-v-1] + shift - 5;
+
+ def map_scale(self, v):
+ return self.map_scale2(v, self.scale_mode, self.key_shift)
+
+ def note2str(self, note):
+ rstr = str((int)((note+36)/12)) + "."
+ if note%12 < 10:
+ rstr += "0"
+ rstr += str(note%12)
+ return rstr
+
+ def knote_on(self, csound, inst, note, nid):
+ v = 1
+ if inst == 8:
+ eventStr = "i5" + str(inst) + "." + str(nid) + " 0 -1 " + str(v) + " " + str(note)
+ elif inst == 7:
+ eventStr = "i5" + str(inst) + "." + str(nid) + " 0 -1 " + str(v) + " " + self.note2str(note-12)
+ else:
+ eventStr = "i5" + str(inst) + "." + str(nid) + " 0 -1 " + str(v) + " " + self.note2str(note)
+ self.lastNoteOnTime = self.currentTime
+ csound.sendLinevt(eventStr)
+
+ def knote_off(self, csound, inst, note, nid):
+ if inst == 8:
+ return
+ if inst == 7:
+ eventStr = "i-5" + str(inst) + "." + str(nid) + " 0 0 1 " + self.note2str(note-12)
+ elif inst == 0:
+ eventStr = "i-5" + str(inst) + "." + str(nid) + " 0.45 0 1 " + self.note2str(note-12)
+ else:
+ eventStr = "i-5" + str(inst) + "." + str(nid) + " 0 0 1 " + self.note2str(note)
+ if _showCSoundMsg:
+ print "CSound Event: " + eventStr
+ csound.sendLinevt(eventStr)
+
+ def note_on(self, csound, inst, note, toolbar_sound = 0, v = 1):
+ if toolbar_sound == 0:
+ if inst == 8:
+ eventStr = "i5" + str(inst) + " 0 -1 " + str(v) + " " + str(note)
+ elif inst == 7:
+ eventStr = "i5" + str(inst) + " 0 -1 " + str(v) + " " + self.note2str(note-12)
+ else:
+ eventStr = "i5" + str(inst) + " 0 -1 " + str(v) + " " + self.note2str(note)
+ self.lastNoteOnTime = self.currentTime
+ else:
+ if inst == 8:
+ eventStr = "i" + str(inst) + " 0 0.8 1 0"
+ elif inst == 7:
+ eventStr = "i" + str(inst) + " 0 0.8 1 " + self.note2str(note-12)
+ else:
+ eventStr = "i" + str(inst) + " 0 0.8 1 " + self.note2str(note)
+ if _showCSoundMsg:
+ print "CSound Event: " + eventStr
+ csound.sendLinevt(eventStr)
+
+ def note_off(self, csound, inst, note):
+ if inst == 8:
+ return
+# if self.currentTime - self.lastNoteOnTime < 0.25:
+# d = 0.35
+# else:
+ d = 0
+ if inst == 7:
+ eventStr = "i-5" + str(inst) + " " + str(d) + " 0 1 " + self.note2str(note-12)
+ elif inst == 0:
+ eventStr = "i-5" + str(inst) + " " + str(0.45) + " 0 1 " + self.note2str(note-12)
+ else:
+ eventStr = "i-5" + str(inst) + " " + str(d) + " 0 1 " + self.note2str(note)
+ if _showCSoundMsg:
+ print "CSound Event: " + eventStr
+ csound.sendLinevt(eventStr)
+
+ def drag_on_vol(self, csound, toolsel, colorsel, gy, v):
+ if colorsel == 7:
+ note = gy
+ else:
+ note = self.map_scale(gy)
+ if self.last_note !=-1 :
+ self.note_off(csound, colorsel+1, self.last_note)
+ self.last_note = note
+ self.note_on(csound, colorsel+1, note, 0, self.floor3(v))
+
+ def keyboard_change_instrument(self, csound, prev_color):
+ for i in range(self.ngrid_v):
+ if prev_color == 7:
+ note = i
+ else:
+ note = self.map_scale(i)
+ if self.keyon[i] == 1:
+ self.knote_off(csound, colorsel+1, note, i)
+ self.keyon[i] = 0
+
+ def keyboard_press(self, csound, colorsel, gy):
+ if _showDebugMsg:
+ print "note on: " + str(colorsel+1) + "," + str(gy)
+ if self.keyon[gy] == 1:
+ return
+ if colorsel == 7:
+ note = gy
+ else:
+ note = self.map_scale(gy)
+ self.knote_on(csound, colorsel+1, note, gy)
+ self.main.canvas.write_note_keyboard(gy)
+ self.keyon[gy] = 1
+
+ def keyboard_release(self, csound, colorsel, gy):
+ if _showDebugMsg:
+ print "note off: " + str(colorsel+1) + "," + str(gy)
+ if colorsel == 7:
+ note = gy
+ else:
+ note = self.map_scale(gy)
+ self.knote_off(csound, colorsel+1, note, gy)
+ self.keyon[gy] = 0
+
+ def drag_on(self, csound, toolsel, colorsel, gy):
+ if toolsel != 2:
+ return
+
+ if colorsel == 7:
+ note = gy
+ else:
+ note = self.map_scale(gy)
+ if note != self.last_note: # to be fix, note != 0
+ if self.last_note !=-1 :
+ self.note_off(csound, colorsel+1, self.last_note)
+ self.last_note = note
+ self.note_on(csound, colorsel+1, note)
+
+ def drag_off(self, csound, toolsel, colorsel):
+ if not (toolsel == 2 or toolsel == -1 or toolsel == 0):
+ return
+ if self.last_note !=-1 :
+ self.note_off(csound, colorsel+1, self.last_note)
+ self.last_note = -1
+
+ def timeUpdate(self, time):
+ self.currentTime = (float)(time)
+ if self.time_continue < self.currentTime:
+ self.continue_music()
+# print "time = %.3f" % (self.currentTime - self.startSesstionTime)
+# print "%.3f" % (self.backup_event[self.play_continue][1])
+ #print "time = %.3f %.3F" % (self.currentTime - self.startSessionTime, self.backup_event[self.play_continue][1])
+# print "note time = %.3f" % self.backup_event[self.play_continue][1]
+# if self.play_continue != -1 and self.backup_event[self.play_continue][1] - self.currentTime + self.startSessionTime < 0.5:
+# self.continue_music()
+ self.main.canvas.highlight_grid()
+
+ def tempoChange(self, sval):
+ odiv = self.grid_tdiv
+ ndiv = 0.1 * pow(6.25, 1-sval)
+ if self.play_state != -2:
+ if _showDebugMsg:
+ print "%.2f %.2f %.2f" % (self.currentTime - self.startSessionTime, self.score_start_time, self.score_end_time)
+ self.main.csound.sendClearLines()
+ g = (self.currentTime - self.startSessionTime) / odiv
+ self.score_start_time = (self.score_start_time + self.currentTime - self.startSessionTime) / odiv * ndiv
+ self.score_end_time = (self.score_end_time - self.currentTime + self.startSessionTime) / odiv * ndiv
+ self.startSessionTime = self.currentTime
+ limit = 100
+ cnt = 0
+ con = -1
+ if _showDebugMsg:
+ print "%.1f %.2f %.2f" % (g, self.score_start_time, self.score_end_time)
+ for i in range(self.ecnt):
+ st = self.backup_events[i][1]
+ if st == -1:
+ continue;
+ if st / odiv + 0.1 < g:
+ self.backup_events[i][1] = -1
+ continue;
+ en = self.backup_events[i][2]
+ st = (st / odiv - g) * ndiv
+ en = en / odiv * ndiv
+ if st < 0:
+ en = en + st
+ st = 0
+ st = self.floor3(st)
+ en = self.floor3(en)
+ if self.backup_events[i][0] == 8:
+ n = self.backup_events[i][4]
+ else:
+ n = self.note2str(self.map_scale(self.backup_events[i][4]))
+ estr = "i" + str(self.backup_events[i][0]) + " " + str(st) + " " + str(en) + " " + str(self.backup_events[i][3]) + " " + str(n)
+ self.backup_events[i][1] = st
+ self.backup_events[i][2] = en
+ #if _showGraphcisEvent:
+ # print estr
+ if cnt < limit:
+ self.main.csound.sendLinevt(estr)
+ elif con == -1:
+ con = i
+ cnt = cnt + 1
+ if cnt >= limit:
+ self.time_continue = self.backup_events[con][1] + self.currentTime - 0.5
+ self.play_continue = con
+ else:
+ self.play_continue = -1
+ self.time_continue = 99999999
+ self.grid_tdiv = ndiv
+
+ def floor3(self, v):
+ return 1.0 * (int) ((v + 0.0005) * 1000) / 1000
+
+ def score2events(self, score, cut, div = 0):
+ if div == 0:
+ div = self.grid_tdiv
+ events = list()
+
+ if self.main.toolbar.from_start == 1:
+ first_note_time = 0
+ else:
+ first_note_time = -1
+ end_note_time = -1
+
+ for i in range(self.ngrid_h):
+ for j in range(self.ngrid_v):
+ for k in range(8):
+ if score[k][i][j] != 0 and (i == 0 or score[k][i-1][j] == 0 or cut[k][i-1][j] == 1):
+ if first_note_time == -1:
+ first_note_time = div*i
+ len = 1
+ while i+len < self.ngrid_h and score[k][i+len][j] != 0 and cut[k][i+len-1][j] == 0:
+ len = len + 1
+# if k == 7:
+# n = j
+# else:
+# n = self.note2str(self.map_scale(j))
+ st = div*i - first_note_time
+ du = div*len
+ if end_note_time == -1 or end_note_time < st+du:
+ end_note_time = st+du
+ if k == 7: # percussion
+ du = du * 3
+ event = [k+1, self.floor3(st), self.floor3(du), self.floor3(score[k][i][j]), j]
+ events.append(event)
+ if self.main.toolbar.record == 1:
+ if self.main.toolbar.sval >= 0.5:
+ p = 4
+ elif self.main.toolbar.sval >= 0.1:
+ p = 2
+ else:
+ p = 1
+ if i % p != 0:
+ continue
+ st = div*i - first_note_time
+ du = 3*div
+ if end_note_time == -1 or end_note_time < st+du:
+ end_note_time = st+du
+ event = [8, self.floor3(st), self.floor3(du), 0.5, 1]
+ events.append(event)
+
+
+ return (events, first_note_time, end_note_time)
+
+ def read_score(self, filename):
+ stream = open(filename, 'r')
+ map = self.zeros3(8, self.ngrid_h, self.ngrid_v)
+ cut = self.zeros3(8, self.ngrid_h, self.ngrid_v)
+ try:
+ (sval, mode, shift, type, author, title, desc, note) = (0.25, 0, 0, 0, "", "", "", "") # default
+ cnt = 0
+ flag = 0
+ for line in stream:
+ if line[0] == "=":
+ flag = 1
+ continue
+ n = line.split(" ")
+ if flag == 0:
+ if line[0] == "T": # tempo_slider_value
+ sval = self.toFloat(n[1])
+ elif line[0] == "S": # scale_mode
+ n[1] = self.toStr(n[1])
+ for i in range(len(self.scale_list)):
+ if n[1] == self.scale_list[i]:
+ mode = i
+ elif line[0] == "P": # pitch_shift
+ shift = self.toInt(n[1])
+ elif line[0] == "A":
+ line = self.toStr(line).replace("Author: ","")
+ author = line
+ elif line[0] == "B": # brick_type
+ type = self.toInt(n[1])
+ elif line[0] == "C": # title
+ title = self.toStr(line).replace("CTitle: ","")
+ elif line[0] == "D": #description
+ desc = self.toStr(line).replace("Description: ","")
+ elif line[0] == "N": #note
+ note = self.toStr(line).replace("Note: ","")
+ else: # read score
+ (p1,p2,p3,p4,p5) = ((int)(n[0])-1,(int)(n[1]),(int)(n[2]),(int)(n[3]),(float)(n[4]))
+ if p2 != 0 and map[p1][p2-1][p4] != 0:
+ cut[p1][p2-1][p4] = 1
+ for i in range(p3):
+ map[p1][p2+i][p4] = p5
+ cnt = cnt + 1
+ finally:
+ stream.close()
+ return (map, cut, sval, mode, shift, type, author, title, desc, note)
+
+ def read_journal(self, filename):
+ (self.map, self.cut, sval, self.scale_mode, self.key_shift, type, author, self.title, self.description, self.note) = self.read_score(filename)
+ if self.main.toolbar.change_slider_val(sval - self.main.toolbar.sval):
+ self.tempoChange(self.main.toolbar.sval)
+
+ def read_mpscore(self, filename):
+ self.filename = filename
+ (self.map, self.cut, sval, self.scale_mode, self.key_shift, type, author, self.title, self.description, self.note) = self.read_score("myscore/" + filename)
+ if self.main.toolbar.change_slider_val(sval - self.main.toolbar.sval):
+ self.tempoChange(self.main.toolbar.sval)
+
+ def write_journal(self, filename):
+ self.write_score(filename, self.map, self.cut, self.grid_tdiv, self.scale_mode, self.key_shift)
+
+ def write_mpscore(self):
+ filename = "myscore/" + self.filename
+ self.write_score(filename, self.map, self.cut, self.grid_tdiv, self.scale_mode, self.key_shift)
+ self.upload_mpscore()
+
+ def upload_mpscore(self):
+ if self.main.ftp_status == 0:
+ return
+ try:
+ stream = open("myscore/" + self.filename, 'r')
+ msg = self.main.ftp.storlines("STOR " + self.filename, stream)
+ print "ftp::STOR " + self.filename + "....." + msg
+ stream.close()
+ except:
+ print "ftp error...."
+ self.main.ftp_status = 0
+
+ def write_score(self, filename, score, cut, grid_tdiv, scale_mode, pitch_shift, type = 0):
+ stream = open(filename, 'w')
+ stream.writelines("Author: " + self.main.username + "\n")
+ stream.writelines("Brick_type: " + str(type) + "\n")
+ stream.writelines("Tempo_slider_val: " + str(self.main.toolbar.sval) + "\n")
+ stream.writelines("Scale_mode: " + self.scale_list[scale_mode] + "\n")
+ stream.writelines("Pitch_shift: " + str(self.key_shift) + "\n")
+ if filename.endswith("mps"):
+ stream.writelines("CTitle: " + self.title + "\n")
+ stream.writelines("Description: " + self.description + "\n")
+ stream.writelines("Note: " + self.note + "\n")
+ stream.writelines("==============================\n")
+ for i in range(self.ngrid_h):
+ for k in range(8):
+ for j in range(self.ngrid_v):
+ if score[k][i][j] != 0 and (i == 0 or score[k][i-1][j] == 0 or cut[k][i-1][j] == 1):
+ len = 1
+ while i+len < self.ngrid_h and score[k][i+len][j] != 0 and cut[k][i+len-1][j] == 0:
+ len = len + 1
+ stream.writelines(str(k+1) + " " + str(i) + " " + str(len) + " " + str(j) + " " + str(self.floor3(score[k][i][j])) + "\n")
+ # instrument - time (x) - duration - pitch (y) - volume
+ stream.close()
+
+ def stop_music(self, csound):
+ if self.play_state == -1:
+ self.main.canvas.highlight_grid(True)
+ self.play_state = -2
+ self.main.toolbar.update()
+ csound.sendClearLines()
+
+ #def sendEvents(self):
+ #for i in range(self.ecnt):
+ #str = "i" + str(events
+ #csound.sendLinevt()
+ ## while self.epcnt < self.ecnt:
+ ## self.play_time
+ #for i in range(len(events)):
+ #csound.sendLinevt(events[i])
+
+ def continue_music(self):
+ print "continue_music"
+ csound = self.main.csound
+ if csound.status != 1 or self.play_continue == -1:
+ return
+ td = self.currentTime - self.startSessionTime
+ events = self.backup_events
+ flag = 0
+ limit = 72
+ for j in range(self.ecnt-self.play_continue):
+ if j == limit:
+ flag = 1
+ break
+ i = j + self.play_continue
+ if events[i][0] == 8:
+ estr = "i" + str(events[i][0]) + " " + str(events[i][1]-td) + " " + str(events[i][2]) + " " + str(events[i][3]) + " " + str(events[i][4])
+ elif events[i][0] == 7:
+ n = self.note2str(self.map_scale(events[i][4])-12)
+ estr = "i" + str(events[i][0]) + " " + str(events[i][1]-td) + " " + str(events[i][2]) + " " + str(events[i][3]) + " " + str(n)
+ else:
+ n = self.note2str(self.map_scale(events[i][4]))
+ estr = "i" + str(events[i][0]) + " " + str(events[i][1]-td) + " " + str(events[i][2]) + " " + str(events[i][3]) + " " + str(n)
+ csound.sendLinevt(estr)
+ if flag == 1:
+ self.play_continue = self.play_continue + limit
+ self.time_continue = events[self.play_continue][1] + self.startSessionTime - 0.5
+ else:
+ self.play_continue = -1
+ self.time_continue = 99999999
+
+ def play_music(self, csound):
+ print "Csound.status = %d" % csound.status
+ if csound.status != 1:
+ return
+ if self.play_state == -1:
+ self.main.canvas.highlight_grid(True)
+ self.main.canvas.last_gx_key = -1
+ csound.sendClearLines()
+ self.startSessionTime = self.currentTime
+
+ if self.select_state == 0:
+ (events, st, et) = self.score2events(self.map, self.cut)
+ else:
+ (events, st, et) = self.score2events(self.sel, self.scut)
+ self.backup_events = events
+ self.ecnt = len(events) #length
+ limit = 144
+ if st != -1:
+ if self.ecnt > limit:
+ t = limit
+ self.play_continue = limit
+ self.time_continue = events[limit][1] + self.currentTime - 0.5
+# print "time to continue %.3f" % events[200][1]
+ else:
+ t = self.ecnt
+ self.play_continue = -1
+ self.time_continue = 99999999
+ for i in range(t):
+ if events[i][0] == 8:
+ estr = "i" + str(events[i][0]) + " " + str(events[i][1]) + " " + str(events[i][2]) + " " + str(events[i][3]) + " " + str(events[i][4])
+ elif events[i][0] == 7:
+ n = self.note2str(self.map_scale(events[i][4])-12)
+ estr = "i" + str(events[i][0]) + " " + str(events[i][1]) + " " + str(events[i][2]) + " " + str(events[i][3]) + " " + str(n)
+ else:
+ n = self.note2str(self.map_scale(events[i][4]))
+ estr = "i" + str(events[i][0]) + " " + str(events[i][1]) + " " + str(events[i][2]) + " " + str(events[i][3]) + " " + str(n)
+ csound.sendLinevt(estr)
+
+# self.sendEvents()
+# self.play_time = 0
+ self.play_state = -1
+ self.score_start_time = st
+ self.score_end_time = et
+ else:
+ self.play_state = -2
+ self.main.toolbar.update()
+
+ if _showCSoundMsg:
+ print "Playing CSound Music..."
diff --git a/Musicpainter.py b/Musicpainter.py
new file mode 100644
index 0000000..03fc9e6
--- /dev/null
+++ b/Musicpainter.py
@@ -0,0 +1,920 @@
+#!/usr/bin/env python
+
+# Musicpainter-11.activity Wu-Hsi Li
+# updated, Feb 26, 2014
+
+from ftplib import FTP
+import time
+import pygtk
+pygtk.require('2.0')
+import gtk
+
+import gobject
+import cairo
+import pango
+import random
+
+_noCsound = False
+#_noCsound = True
+
+platform = "windows-1024"
+#platform = "sugar-xo"
+#platform = "linux"
+
+#from MelodicCulture import *
+from copy import copy
+import sys
+import os
+
+from datetime import datetime
+from gtk.gdk import CONTROL_MASK
+
+from Brick import *
+from MPScore import *
+from Canvas import *
+from BricksArea import *
+from ToolbarArea import *
+from BrickBrowser import *
+
+import common.Config as Config
+from common.Generation.GenerationConstants import GenerationConstants
+from common.Util.NoteDB import Note
+from common.Util.CSoundNote import CSoundNote
+from common.Util.CSoundClient import new_csound_client
+from common.Util import InstrumentDB
+
+#from CsoundXOAgent import CsoundXOAgent
+
+# ======= for linux ==========
+
+#path = "/home/olpc/Activities/Musicpainter.activity/myscore/"
+
+# ======= for windows ========
+
+path = "myscore"
+
+# ============================
+
+_showFunctionCall = False
+_showEvent = False
+
+class Musicpainter:
+
+ def __init__(self):
+ self.hasCSound = False
+ self.username = ""
+ self.cursor_area = 2
+
+ def destroy_callback(self, data):
+ if _showFunctionCall:
+ print "Musicpainter::destroy_callback()"
+ self.csound.api.after_gtk_destroy()
+ self.destroy(self)
+
+ def main(self):
+ self.platform = platform
+ print "set platform = " + platform
+ toplevel_window = gtk.Window(gtk.WINDOW_TOPLEVEL)
+ self.init(toplevel_window)
+ gtk.main()
+
+ return 0
+
+ def dcallback(self, data):
+ print "deactivate callback: " + data
+
+ def rcallback(self, data):
+ if data == "OK":
+ print "callback: instance reactivated"
+ elif data == "NOTOK":
+ print "callback: failed to reactivate, try again"
+ self.csound.api.sendDeactivate()
+ time.sleep(1)
+ self.csound.api.sendReactivateWithCallback(self.rcallback)
+ else:
+ print "reactivate callback: " + data
+
+ def deactivate(self):
+ if _showFunctionCall:
+ print "Musicpainter::deactivate()"
+ if self.hasCSound == True:
+ #self.score.stop_music(self.csound)
+ self.csound.sendClearLines()
+ self.score.play_state = -2
+ self.csound.api._deactivate = True
+ self.csound.api.sendDeactivate()
+ time.sleep(1)
+
+ def reactivate(self):
+ if _showFunctionCall:
+ print "Musicpainter::reactivate()"
+ if self.hasCSound == True:
+ print "hasCSound = " + str(self.hasCSound) + ", isConnected = " + str(self.csound.api._isConnected)
+ else:
+ print "hasCSound = " + str(self.hasCSound)
+ time.sleep(1)
+ if self.hasCSound == True and self.csound.api._isConnected == True:
+ self.csound.api._deactivate = False
+ self.csound.api.sendReactivateWithCallback(self.rcallback)
+ else:
+ if self.hasCSound == True:
+ self.csound.api._deactivate = False
+ print "To call csound.recover()...."
+ self.hasCSound = self.csound.recover()
+
+ def initSugar(self, toplevel_window, name):
+ self.platform = "sugar-xo" #called from MusicpainterActivity, set platform to sugar
+ self.username = name
+ self.hasCSound = False
+ self.init(toplevel_window)
+ print "Set platform = " + self.platform + ", username is " + name
+
+ def init(self, toplevel_window):
+
+ self.init_data()
+ self.init_csound()
+ self.init_graphics()
+
+ self.window = toplevel_window
+
+ # remove any children of the window that Sugar may have added
+ #for widget in self.window.get_children():
+ #self.window.remove(widget)
+ self.window.set_title("Music Painter")
+ self.window.set_name ("Music Painter") # i guess this is for XO
+ self.window.set_resizable(False)
+
+ self.window.connect("destroy", self.destroy0)
+ self.window.connect("delete_event", self.delete_event)
+ self.window.connect("key_press_event", self.key_press_event)
+ self.window.connect("key_release_event", self.key_release_event)
+
+ self.window.modify_bg(gtk.STATE_NORMAL, gtk.gdk.Color(55040, 55040, 65535))
+
+ self.layout = gtk.Fixed()
+ self.login_layout = gtk.Fixed()
+ self.browser_layout = gtk.Fixed()
+ self.msg1_layout = gtk.Fixed()
+ self.msg2_layout = gtk.Fixed()
+
+ if self.platform == "sugar-xo": # use xo owner name as username
+ self.window.set_canvas(self.layout)
+ self.key_lock = 0
+ self.score.load_profile(self.username)
+ self.prepare_login_layout()
+ self.init_ftp()
+ self.prepare_layout()
+ #self.repare_browser_layout()
+ self.window.set_title("Music Painter - " + self.username)
+ else:
+ self.window.add(self.login_layout)
+ self.prepare_login_layout()
+ self.key_lock = 1
+
+ self.prepare_msg1_layout()
+ self.prepare_msg2_layout()
+
+ if self.platform != "sugar-xo":
+ self.init_ftp()
+ self.window.show_all()
+
+ def init_csound(self):
+ self.hasCSound = False
+ if not _noCsound and self.hasCSound == False:
+ self.csound = CsoundXOAgent("localhost", random, self.score.timeUpdate, self.platform)
+ time.sleep(2)
+ self.hasCSound = (self.csound.status == 1)
+ if self.hasCSound == False:
+ self.hasCSound = self.csound.recover()
+
+ def init_graphics(self):
+
+ self.width = gtk.gdk.screen_get_default().get_width()
+ self.height = gtk.gdk.screen_get_default().get_height()
+
+# self.width, self.height = 1024, 768 #standard
+# self.width, self.height = 1600, 900
+# self.width, self.height = 1280, 800 #lenovo x201
+# self.width, self.height = 1200, 900 #sugar 1.5
+
+ self.cx = (int)(0.09 * self.width)
+
+ self.toolbararea_width = self.width
+ self.canvas_width = self.width
+ self.bricksarea_width = self.width
+ if self.height <= 800:
+ self.toolbararea_height = 56
+ else:
+ self.toolbararea_height = 64
+# self.toolbararea_height = 56
+
+ v = 0.65 * self.height / 18
+ self.canvas_height = (int)(v * 18)
+ self.bricksarea_height = (int)(self.height / 4)
+
+ self.total_height = self.toolbararea_height + self.canvas_height + self.bricksarea_height
+
+ def init_data(self):
+ self.ftp_status = 0
+ self.save_as = False
+
+ self.ngrid_h = 64
+ self.ngrid_v = 18
+ self.score = MPScore(self.ngrid_h, self.ngrid_v, self.platform, self)
+
+ self.press_ctrl = 0
+ self.key_lock = 1
+ return
+
+ def destroy(self, widget, data=None):
+ if _showFunctionCall:
+ print "Music_painter::destroy()"
+ gtk.main_quit()
+
+ def destroy0(self, widget, data=None):
+ if _showFunctionCall:
+ print "Music_painter::destroy0()"
+ if not _noCsound and self.hasCSound == True:
+ self.csound.sendClearLines()
+ self.csound.api._deactivate = True
+ self.csound.close()
+
+ if self.ftp_status == 1:
+ self.log_ftp(False)
+ self.ftp.quit()
+ try:
+ self.score.save_profile(self.username)
+ except:
+ print "Unable to save profile"
+ gtk.main_quit()
+
+ def log_ftp(self, flag = True):
+ try:
+ nowstr = str(datetime.now())[:19].replace(":","-")
+ stream = open("blank.sco", 'r')
+ if flag:
+ log = self.username + "_is_online_" + nowstr + ".log"
+ else:
+ log = self.username + "_leaves_" + nowstr + ".log"
+ self.ftp.storlines("STOR log/" + log, stream)
+ stream.close()
+ except:
+ self.ftp_status = 0
+
+ def init_ftp(self):
+ try:
+ print "ip = " + self.ip
+ self.ftp = FTP(self.ip, "musicpainter", "medialab")
+ self.score.srv_brick_list = self.ftp.nlst("*.mp*")
+ self.ftp_status = 1
+ if self.platform == "sugar-xo":
+ self.log_ftp()
+ print "ftp init successful"
+ except:
+ print "ftp exception"
+ self.score.srv_brick_list = []
+ self.ftp_status = 0
+
+ def prepare_browser_layout(self):
+
+ if self.platform == "sugar-xo":
+ font = 'lucida sans unicode 6'
+ font2 = 'lucida sans unicode 5'
+ else:
+ font = 'lucida sans unicode 11'
+ font2 = 'lucida sans unicode 9'
+
+ font_desc = pango.FontDescription(font)
+ font_desc2 = pango.FontDescription(font2)
+
+ self.model1 = gtk.ListStore(gobject.TYPE_STRING)
+ self.model1.append(["All Authors"])
+ self.update_author = False
+ self.author_box = gtk.ComboBox(self.model1)
+ self.author_box.set_active(0)
+ cell1 = gtk.CellRendererText()
+ cell1.set_property('font-desc', font_desc)
+ self.author_box.pack_start(cell1, True)
+ self.author_box.add_attribute(cell1, 'text', 0)
+
+ self.model2 = gtk.ListStore(gobject.TYPE_STRING)
+ self.model2.append(["Compositions"])
+ self.model2.append(["All Bricks"])
+ self.model2.append(["Melody Bricks"])
+ self.model2.append(["Rhythm Bricks"])
+ self.type_box = gtk.ComboBox(self.model2)
+ self.type_box.set_active(1)
+ cell2 = gtk.CellRendererText()
+ cell2.set_property('font-desc', font_desc)
+ self.type_box.pack_start(cell2, True)
+ self.type_box.add_attribute(cell2, 'text', 0)
+
+ self.model3 = gtk.ListStore(gobject.TYPE_STRING)
+ self.model3.append(["All Scales"])
+ self.model3.append(["Major Scale"])
+ self.model3.append(["Minor Scale"])
+ self.model3.append(["Chromatic Scale"])
+ self.model3.append(["Chinese Scale"])
+ self.model3.append(["Japanese Scale"])
+ self.model3.append(["Blue Note Scale"])
+ self.scale_box = gtk.ComboBox(self.model3)
+ self.scale_box.set_active(0)
+ cell3 = gtk.CellRendererText()
+ cell3.set_property('font-desc', font_desc)
+ self.scale_box.pack_start(cell3, True)
+ self.scale_box.add_attribute(cell3, 'text', 0)
+
+ self.browser = BrickBrowser(self.canvas_width, self.canvas_height - 108, self.platform, self)
+
+ self.author_box.connect_object("changed", self.browser.combo_changed, self.window)
+ self.type_box.connect_object("changed", self.browser.combo_changed, self.window)
+ self.scale_box.connect_object("changed", self.browser.combo_changed, self.window)
+
+ label1 = gtk.Label("Author: ")
+ label1.modify_font(font_desc)
+
+ self.browser.author_label = gtk.Label("") # author
+ self.browser.author_label.modify_font(font_desc)
+ self.browser.author_label.modify_fg(gtk.STATE_NORMAL, gtk.gdk.Color(16384, 16384, 16384))
+
+ label2 = gtk.Label("Type: ")
+ label2.modify_font(font_desc)
+
+ self.browser.type_label = gtk.Label("") # brick_type
+ self.browser.type_label.modify_font(font_desc)
+ self.browser.type_label.modify_fg(gtk.STATE_NORMAL, gtk.gdk.Color(16384, 16384, 16384))
+
+ label3 = gtk.Label("Scale: ")
+ label3.modify_font(font_desc)
+
+ self.browser.scale_label = gtk.Label("") # scale_type
+ self.browser.scale_label.modify_font(font_desc)
+ self.browser.scale_label.modify_fg(gtk.STATE_NORMAL, gtk.gdk.Color(16384, 16384, 16384))
+
+ label4 = gtk.Label("Filename: ")
+ label4.modify_font(font_desc)
+
+ self.browser.filename_label = gtk.Label("") # filename
+ self.browser.filename_label.modify_font(font_desc)
+ self.browser.filename_label.modify_fg(gtk.STATE_NORMAL, gtk.gdk.Color(16384, 16384, 16384))
+
+ label5 = gtk.Label("Title: ")
+ label5.modify_font(font_desc)
+ self.browser.title_label = gtk.Label("") # title
+ self.browser.title_label.modify_font(font_desc2)
+ self.browser.title_label.modify_fg(gtk.STATE_NORMAL, gtk.gdk.Color(16384, 16384, 16384))
+
+ label6 = gtk.Label("Description: ")
+ label6.modify_font(font_desc)
+ self.browser.desc_label = gtk.Label("")
+ self.browser.desc_label.modify_font(font_desc2)
+ self.browser.desc_label.modify_fg(gtk.STATE_NORMAL, gtk.gdk.Color(16384, 16384, 16384))
+
+ label7 = gtk.Label("Note: ")
+ label7.modify_font(font_desc)
+ self.browser.note_label = gtk.Label("")
+ self.browser.note_label.modify_font(font_desc2)
+ self.browser.note_label.modify_fg(gtk.STATE_NORMAL, gtk.gdk.Color(16384, 16384, 16384))
+
+ self.browser_layout.modify_bg(gtk.STATE_NORMAL, gtk.gdk.Color(55040, 55040, 65535))
+ self.browser_layout.put(self.browser, 0, self.toolbararea_height)
+
+ self.browser_layout.put(self.author_box, 180, 15)
+ self.browser_layout.put(self.type_box, 430, 15)
+ self.browser_layout.put(self.scale_box, 710, 15)
+
+ self.ty = self.toolbararea_height + self.browser.cy + self.browser.thei + 8
+ s = 0
+# self.ty = self.canvas_height - 120
+# if self.platform == "sugar-xo":
+# s = 188
+# else:
+# s = 0
+ self.cx2 = (int)(self.cx + 0.45 * (self.width - self.cx))
+ self.browser_layout.put(label1, self.cx+2, self.ty)
+ self.browser_layout.put(label2, self.cx+2, self.ty+20)
+ self.browser_layout.put(label3, self.cx+2, self.ty+40)
+ self.browser_layout.put(label4, self.cx+2, self.ty+60)
+ self.browser_layout.put(label5, self.cx2+2, self.ty)
+ self.browser_layout.put(label6, self.cx2+2, self.ty+20)
+ self.browser_layout.put(label7, self.cx2+2, self.ty+40)
+
+ self.browser_layout.put(self.browser.author_label, self.cx+82, self.ty)
+ self.browser_layout.put(self.browser.type_label, self.cx+82, self.ty+20)
+ self.browser_layout.put(self.browser.scale_label, self.cx+82, self.ty+40)
+ self.browser_layout.put(self.browser.filename_label, self.cx+82, self.ty+60)
+ self.browser_layout.put(self.browser.title_label, self.cx2+112, self.ty)
+ self.browser_layout.put(self.browser.desc_label, self.cx2+112, self.ty+20)
+ self.browser_layout.put(self.browser.note_label, self.cx2+112, self.ty+40)
+
+ self.browser_layout.show()
+
+ def callback1(self, widget, entry = None):
+ self.save_working_brick = True
+ self.destroy0(widget)
+
+ def callback2(self, widget, entry = None):
+ self.save_working_brick = False
+ self.destroy0(widget)
+
+ def callback3(self, widget, entry = None):
+ if self.platform == "sugar-xo":
+ self.window.set_canvas(self.layout)
+ else:
+ self.window.remove(self.msg1_layout)
+ self.window.add(self.layout)
+ self.window.show_all()
+
+ def callback4(self, widget, entry = None):
+ self.score.title = self.entry2.get_text()
+ self.score.description = self.entry3.get_text()
+ self.score.write_mpscore()
+ self.window.set_title("Music Painter - " + self.username)
+ self.score.is_edited = False
+ self.callback6(widget)
+
+ def callback5(self, widget, entry = None):
+ if not self.save_as:
+ self.score.filename = self.username + "_0_" + str(self.score.scale_mode) + "_piece" + str(random.randint(0, 999999)) + ".mps"
+ self.mlabel5.set_text("Filename: " + self.score.filename)
+ self.save_as = True
+ self.sbutton2.hide()
+
+ def callback6(self, widget, entry = None):
+ if self.platform == "sugar-xo":
+ self.window.set_canvas(self.layout)
+ else:
+ self.window.remove(self.msg2_layout)
+ self.window.add(self.layout)
+
+ self.window.show_all()
+ self.key_lock = 0
+
+ def back_callback(self, widget, entry = None):
+ return
+
+ def prepare_layout(self):
+# print "prepare layout, platform = " + self.platform
+ self.canvas = Canvas(self.canvas_width, self.canvas_height, self.platform, self)
+ self.layout.put(self.canvas, 0, self.toolbararea_height)
+
+ self.toolbar = ToolbarArea(self.toolbararea_width, self.toolbararea_height, self.platform, self)
+ self.layout.put(self.toolbar, 0, 0)
+
+ self.bricksarea = BricksArea(self.bricksarea_width, self.bricksarea_height, self.platform, self)
+ self.layout.put(self.bricksarea, 0, self.canvas_height + self.toolbararea_height)
+
+ self.hid_entry = gtk.Entry()
+ self.hid_entry.set_size_request(0, 0)
+ self.hid_entry.set_max_length(0)
+ self.layout.put(self.hid_entry, 0, 0)
+
+ self.grab_focus()
+
+ def grab_focus(self):
+ self.hid_entry.grab_focus()
+
+ def open_config(self):
+ try:
+ stream = open("musicpainter.config", 'r')
+ if self.platform != "sugar-xo":
+ self.username = stream.readline().replace("\n","").replace("\r","")
+ else:
+ stream.readline()
+ self.ip = stream.readline().replace("\n","").replace("\r","")
+ if self.ip == "":
+ self.ip = "musicpainter.media.mit.edu"
+ stream.close()
+ except:
+ if self.username == "":
+ print "set username to Guest"
+ self.username = "Guest"
+ self.ip = "musicpainter.media.mit.edu"
+
+ def prepare_msg1_layout(self):
+ if self.platform == "sugar-xo":
+ font = 'lucida sans unicode 8'
+ else:
+ font = 'lucida sans unicode 12'
+ font_desc = pango.FontDescription(font)
+
+ self.mlabel1 = gtk.Label("Do you want to save the")
+ self.mlabel1.modify_font(font_desc)
+ self.mlabel2 = gtk.Label("bricks in the working area?")
+ self.mlabel2.modify_font(font_desc)
+
+ button1 = gtk.Button("Yes")
+ button1.modify_font(font_desc)
+ button1.set_size_request(60, 30)
+ button1.connect_object("clicked", self.callback1, self.window)
+
+ button2 = gtk.Button("No")
+ button2.modify_font(font_desc)
+ button2.set_size_request(60, 30)
+ button2.connect_object("clicked", self.callback2, self.window)
+
+ button3 = gtk.Button("Back")
+ button3.modify_font(font_desc)
+ button3.set_size_request(60, 30)
+ button3.connect_object("clicked", self.callback3, self.window)
+
+ self.msg1_layout.set_size_request(240, 100)
+ self.msg1_layout.put(self.mlabel1, 20, 10)
+ self.msg1_layout.put(self.mlabel2, 15, 32)
+ self.msg1_layout.put(button1, 15, 65)
+ self.msg1_layout.put(button2, 90, 65)
+ self.msg1_layout.put(button3, 165, 65)
+
+ def prepare_msg2_layout(self):
+ if self.platform == "sugar-xo":
+ font = 'lucida sans unicode 6'
+ else:
+ font = 'lucida sans unicode 12'
+ font_desc = pango.FontDescription(font)
+
+ self.mlabel3 = gtk.Label("Author: ")
+ self.mlabel3.modify_font(font_desc)
+ self.mlabel4 = gtk.Label("Scale: ")
+ self.mlabel4.modify_font(font_desc)
+ self.mlabel5 = gtk.Label("Filename: ")
+ self.mlabel5.modify_font(font_desc)
+ self.mlabel6 = gtk.Label("Note: ")
+ self.mlabel6.modify_font(font_desc)
+ label1 = gtk.Label("Title: ")
+ label1.modify_font(font_desc)
+ label2 = gtk.Label("Description: ")
+ label2.modify_font(font_desc)
+
+ button1 = gtk.Button("OK")
+ button1.modify_font(font_desc)
+ button1.set_size_request(80, 30)
+ button1.connect_object("clicked", self.callback4, self.window)
+
+ self.sbutton2 = gtk.Button("Save As")
+ self.sbutton2.modify_font(font_desc)
+ self.sbutton2.set_size_request(80, 30)
+ self.sbutton2.connect_object("clicked", self.callback5, self.window)
+
+ button3 = gtk.Button("Cancel")
+ button3.modify_font(font_desc)
+ button3.set_size_request(80, 30)
+ button3.connect_object("clicked", self.callback6, self.window)
+
+ self.entry2 = gtk.Entry()
+ self.entry2.set_size_request(720-112-12, 30)
+ self.entry2.set_max_length(100)
+ self.entry2.modify_font(font_desc)
+
+ self.entry3 = gtk.Entry()
+ self.entry3.set_size_request(720-112-12, 30)
+ self.entry3.set_max_length(256)
+ self.entry3.modify_font(font_desc)
+
+ self.entry4 = gtk.Entry()
+ self.entry4.set_size_request(720-112-12, 30)
+ self.entry4.set_max_length(256)
+ self.entry4.modify_font(font_desc)
+ self.entry4.set_editable(False)
+
+ t = 18
+ self.msg2_layout.set_size_request(720, 240-t)
+ self.msg2_layout.put(self.mlabel3, 42, 10) # Author
+ self.msg2_layout.put(self.mlabel4, 323, 10) # Scale
+ self.msg2_layout.put(self.mlabel5, 23, 44) # Filename
+ self.msg2_layout.put(self.mlabel6, 58, 142) # Note
+ self.msg2_layout.put(label1, 60, 76) # Title
+ self.msg2_layout.put(label2, 5, 109) # Description
+ self.msg2_layout.put(button1, 220, 205-t)
+ self.msg2_layout.put(self.sbutton2, 320, 205-t)
+ self.msg2_layout.put(button3, 420, 205-t)
+ self.msg2_layout.put(self.entry2, 112, 74) # Title
+ self.msg2_layout.put(self.entry3, 112, 107) # Description
+ self.msg2_layout.put(self.entry4, 112, 140) # Note
+
+ def prepare_login_layout(self):
+ if self.platform == "sugar-xo":
+ font0 = 'lucida sans unicode 20'
+ font = 'lucida sans unicode 14'
+ else:
+ font0 = 'lucida sans unicode 14'
+ font = 'lucida sans unicode 12'
+ font_desc0 = pango.FontDescription(font0)
+ font_desc = pango.FontDescription(font)
+
+ self.entry = gtk.Entry()
+ if self.platform == "sugar-xo":
+ self.entry.set_size_request(360, 50)
+ else:
+ self.entry.set_size_request(180, 30)
+ self.entry.set_max_length(36)
+ self.entry.connect("activate", self.enter_callback, self.entry)
+ self.open_config()
+ self.entry.set_text(self.username)
+ self.entry.select_region(0, len(self.entry.get_text()))
+ self.entry.modify_font(font_desc)
+
+ stream = open("version.txt",'r')
+ line = stream.readline().replace("\n","")
+ stream.close()
+
+ label1 = gtk.Label("Welcome to Musicpainter! - v" + line)
+ label1.set_justify(gtk.JUSTIFY_CENTER)
+ label1.modify_font(font_desc0)
+
+ frame = gtk.Frame()
+ if self.platform == "sugar-xo":
+ frame.set_size_request(1080, 1)
+ else:
+ frame.set_size_request(344, 1)
+
+ label2 = gtk.Label("My name is ")
+ #label2.set_justify(gtk.JUSTIFY_RIGHT)
+ label2.modify_font(font_desc)
+
+ button1 = gtk.Button("Go")
+ button1.modify_font(font_desc0)
+ if self.platform == "sugar-xo":
+ button1.set_size_request(120, 60)
+ else:
+ button1.set_size_request(40, 30)
+ button1.connect_object("clicked", self.enter_callback, self.window)
+
+ label3 = gtk.Label("Open a canvas in ")
+ label3.modify_font(font_desc)
+
+ model = gtk.ListStore(gobject.TYPE_STRING)
+ model.append(["Major Scale"])
+ model.append(["Minor Scale"])
+ model.append(["Chromatic Scale"])
+ model.append(["Chinese Scale"])
+ model.append(["Japanese Scale"])
+ model.append(["Blue Note Scale"])
+ self.sbox = gtk.ComboBox(model)
+ self.sbox.set_active(0)
+ cell2 = gtk.CellRendererText()
+ cell2.set_property('font-desc', font_desc)
+ self.sbox.pack_start(cell2, True)
+ self.sbox.add_attribute(cell2, 'text', 0)
+
+ if self.platform == "sugar-xo":
+ self.login_layout.set_size_request(1200, 900)
+ self.login_layout.put(label1, 140, 100) # Welcome to Musicpainter!
+ self.login_layout.put(frame, 60, 178)
+ self.login_layout.put(label2, 230, 338) # My name is
+ self.login_layout.put(self.entry, 480, 333)
+ self.login_layout.put(button1, 865, 333) # Go
+ self.login_layout.put(label3, 120, 451)
+ self.login_layout.put(self.sbox, 480, 440)
+ else:
+ self.login_layout.set_size_request(350, 130)
+ self.login_layout.put(label1, 20, 10) # Welcome to Musicpainter!
+ self.login_layout.put(frame, 3, 40)
+ self.login_layout.put(label2, 15, 58) # My name is
+ self.login_layout.put(self.entry, 110, 53)
+ self.login_layout.put(button1, 300, 53) # Go
+ self.login_layout.put(label3, 15, 91)
+ self.login_layout.put(self.sbox, 162, 88)
+
+ def enter_callback(self, widget, entry = None):
+
+ print "My name is %s" % self.entry.get_text()
+ self.username = self.entry.get_text()
+ self.score.scale_mode = self.sbox.get_active()
+ if self.username == "":
+ print "set username to Guest"
+ self.username = "Guest"
+
+ self.window.maximize()
+ self.init_graphics()
+
+ self.score.load_profile(self.username)
+ self.prepare_layout()
+ #self.prepare_browser_layout()
+ self.window.set_title("Music Painter - " + self.username)
+
+ if self.platform == "sugar-xo":
+ self.window.set_canvas(self.layout)
+ else:
+ self.window.remove(self.login_layout)
+ self.window.add(self.layout)
+# self.window.add(self.msg2_layout)
+ self.log_ftp()
+
+# self.window.fullscreen()
+# print "(" + str(gtk.gdk.Screen.get_width()) + "," + str(gtk.gdk.Screen.get_height()) + ")"
+# print self.window.get_size()
+#
+ self.window.show_all()
+
+ self.key_lock = 0
+
+ def delete_event(self, widget, event, data=None):
+ if _showEvent:
+ print "music_painter::delete_event()"
+ if not _noCsound and self.hasCSound:
+ self.csound.sendClearLines()
+ self.csound.api._deactivate = True
+ self.csound.close()
+# time.sleep(3)
+ #self.csound.api.serverShutdown()
+ #self.csound.api.sendDestroyWithCallback(self.destroy_callback)
+
+ if self.ftp_status == 1:
+ self.log_ftp(False)
+ self.ftp.quit()
+ try:
+ self.score.save_profile(self.username)
+ except:
+ print "Unable to save profile"
+ gtk.main_quit()
+
+# self.destroy0(widget)
+
+ return True
+# return False
+
+ def key_release_event(self, widget, event):
+ if not (event.state & CONTROL_MASK):
+ self.press_ctrl = 0
+ if self.key_lock == 1:
+ return
+ keyname = gtk.gdk.keyval_name(event.keyval)
+ if self.cursor_area != 0:
+ if keyname == 'a':
+ self.score.keyboard_release(self.csound, self.toolbar.colorsel, 17)
+ elif keyname == 's':
+ self.score.keyboard_release(self.csound, self.toolbar.colorsel, 16)
+ elif keyname == 'd':
+ self.score.keyboard_release(self.csound, self.toolbar.colorsel, 15)
+ elif keyname == 'f':
+ self.score.keyboard_release(self.csound, self.toolbar.colorsel, 14)
+ elif keyname == 'g':
+ self.score.keyboard_release(self.csound, self.toolbar.colorsel, 13)
+ elif keyname == 'h':
+ self.score.keyboard_release(self.csound, self.toolbar.colorsel, 12)
+ elif keyname == 'j':
+ self.score.keyboard_release(self.csound, self.toolbar.colorsel, 11)
+ elif keyname == 'k' or keyname == 'q':
+ self.score.keyboard_release(self.csound, self.toolbar.colorsel, 10)
+ elif keyname == 'l' or keyname == 'w':
+ self.score.keyboard_release(self.csound, self.toolbar.colorsel, 9)
+ elif keyname == 'semicolon' or keyname == 'e':
+ self.score.keyboard_release(self.csound, self.toolbar.colorsel, 8)
+ elif keyname == 'apostrophe' or keyname == 'r':
+ self.score.keyboard_release(self.csound, self.toolbar.colorsel, 7)
+ elif keyname == 't':
+ self.score.keyboard_release(self.csound, self.toolbar.colorsel, 6)
+ elif keyname == 'y':
+ self.score.keyboard_release(self.csound, self.toolbar.colorsel, 5)
+ elif keyname == 'u':
+ self.score.keyboard_release(self.csound, self.toolbar.colorsel, 4)
+ elif keyname == 'i':
+ self.score.keyboard_release(self.csound, self.toolbar.colorsel, 3)
+ elif keyname == 'o':
+ self.score.keyboard_release(self.csound, self.toolbar.colorsel, 2)
+ elif keyname == 'p':
+ self.score.keyboard_release(self.csound, self.toolbar.colorsel, 1)
+ elif keyname == 'bracketleft':
+ self.score.keyboard_release(self.csound, self.toolbar.colorsel, 0)
+ def key_press_event(self, widget, event):
+ if self.key_lock == 1:
+ return
+ keyname = gtk.gdk.keyval_name(event.keyval)
+ if event.state & CONTROL_MASK:
+ self.press_ctrl = 1
+ if keyname == 'a' or keyname == 'A':
+ self.canvas.select_all()
+ else:
+ print keyname
+ return
+ if keyname == "Left":
+ if self.score.select_state == 1:
+ self.score.drag = deepcopy(self.score.sel)
+ self.score.dcut = deepcopy(self.score.scut)
+ self.canvas.move_selection(0, 0, -1, 0)
+ else:
+ self.toolbar.change_slider_val(-0.05)
+ self.score.tempoChange(self.toolbar.sval)
+ elif keyname == "Right":
+ if self.score.select_state == 1:
+ self.score.drag = deepcopy(self.score.sel)
+ self.score.dcut = deepcopy(self.score.scut)
+ self.canvas.move_selection(0, 0, 1, 0)
+ else:
+ self.toolbar.change_slider_val(0.05)
+ self.score.tempoChange(self.toolbar.sval)
+ elif keyname == "Up":
+ if self.score.select_state == 1:
+ self.score.drag = deepcopy(self.score.sel)
+ self.score.dcut = deepcopy(self.score.scut)
+ self.canvas.move_selection(0, 0, 0, -1)
+ else:
+ self.score.key_shift = self.score.key_shift + 1
+ elif keyname == "Down":
+ if self.score.select_state == 1:
+ self.score.drag = deepcopy(self.score.sel)
+ self.score.dcut = deepcopy(self.score.scut)
+ self.canvas.move_selection(0, 0, 0, 1)
+ else:
+ self.score.key_shift = self.score.key_shift - 1
+# elif keyname == 'p' or keyname == 'P':
+# self.score.play_music(self.csound)
+# elif keyname == 't' or keyname == 'T':
+# self.score.stop_music(self.csound)
+# elif keyname == 's' or keyname == 'S':
+# elif keyname == 'q' or keyname == 'Q':
+# self.destroy0(widget)
+# elif keyname == "space":
+# self.score.play_music(self.csound)
+ elif keyname == "Return":
+ if self.score.play_state == -2:
+ self.score.play_music(self.csound)
+ else:
+ self.score.stop_music(self.csound)
+ elif keyname == "Delete":
+ if self.score.select_state == 1:
+ self.score.delete_selection()
+ self.canvas.update_top()
+# elif keyname == 'd' or keyname == 'D':
+# print "send deactivate()"
+# self.csound.api.sendDeactivateWithCallback(self.dcallback)
+# elif keyname == 'r' or keyname == 'R':
+# print "send reactivate()"
+# self.csound.api.sendReactivateWithCallback(self.rcallback)
+# elif keyname == 'z':
+# self.score.load_collected_list()
+ #list = os.listdir("myscore/bak")
+ #brick = Brick(self.ngrid_h, self.ngrid_v, self)
+ #for i in range(len(list)):
+ #brick.read_score("bak/" + list[i], self.score)
+ #brick.filename = ""
+ #brick.write_score(self.score)
+
+# elif keyname == 'm' or keyname == 'M':
+# self.score.scale_mode = (self.score.scale_mode + 1)%6
+ else:
+ if self.cursor_area != 0:
+ if keyname == '1':
+ self.toolbar.select_instrument(0)
+ elif keyname == '2':
+ self.toolbar.select_instrument(1)
+ elif keyname == '3':
+ self.toolbar.select_instrument(2)
+ elif keyname == '4':
+ self.toolbar.select_instrument(3)
+ elif keyname == '5':
+ self.toolbar.select_instrument(4)
+ elif keyname == '6':
+ self.toolbar.select_instrument(5)
+ elif keyname == '7':
+ self.toolbar.select_instrument(6)
+ elif keyname == '8':
+ self.toolbar.select_instrument(7)
+ elif keyname == 'a':
+ self.score.keyboard_press(self.csound, self.toolbar.colorsel, 17)
+ elif keyname == 's':
+ self.score.keyboard_press(self.csound, self.toolbar.colorsel, 16)
+ elif keyname == 'd':
+ self.score.keyboard_press(self.csound, self.toolbar.colorsel, 15)
+ elif keyname == 'f':
+ self.score.keyboard_press(self.csound, self.toolbar.colorsel, 14)
+ elif keyname == 'g':
+ self.score.keyboard_press(self.csound, self.toolbar.colorsel, 13)
+ elif keyname == 'h':
+ self.score.keyboard_press(self.csound, self.toolbar.colorsel, 12)
+ elif keyname == 'j':
+ self.score.keyboard_press(self.csound, self.toolbar.colorsel, 11)
+ elif keyname == 'k' or keyname == 'q':
+ self.score.keyboard_press(self.csound, self.toolbar.colorsel, 10)
+ elif keyname == 'l' or keyname == 'w':
+ self.score.keyboard_press(self.csound, self.toolbar.colorsel, 9)
+ elif keyname == 'semicolon' or keyname == 'e':
+ self.score.keyboard_press(self.csound, self.toolbar.colorsel, 8)
+ elif keyname == 'apostrophe' or keyname == 'r':
+ self.score.keyboard_press(self.csound, self.toolbar.colorsel, 7)
+ elif keyname == 't':
+ self.score.keyboard_press(self.csound, self.toolbar.colorsel, 6)
+ elif keyname == 'y':
+ self.score.keyboard_press(self.csound, self.toolbar.colorsel, 5)
+ elif keyname == 'u':
+ self.score.keyboard_press(self.csound, self.toolbar.colorsel, 4)
+ elif keyname == 'i':
+ self.score.keyboard_press(self.csound, self.toolbar.colorsel, 3)
+ elif keyname == 'o':
+ self.score.keyboard_press(self.csound, self.toolbar.colorsel, 2)
+ elif keyname == 'p':
+ self.score.keyboard_press(self.csound, self.toolbar.colorsel, 1)
+ elif keyname == 'bracketleft':
+ self.score.keyboard_press(self.csound, self.toolbar.colorsel, 0)
+ elif keyname == 'space':
+ if self.score.play_state == -2:
+ self.score.play_music(self.csound)
+ else:
+ self.score.stop_music(self.csound)
+# else:
+# print keyname + " " + str(event.keyval)
+
+if __name__ == "__main__":
+ musicpainter = Musicpainter()
+ musicpainter.main()
+
diff --git a/MusicpainterActivity.py b/MusicpainterActivity.py
new file mode 100644
index 0000000..7ca1c55
--- /dev/null
+++ b/MusicpainterActivity.py
@@ -0,0 +1,86 @@
+import Musicpainter
+
+from sugar.presence import presenceservice
+from sugar.activity.activity import ActivityToolbox
+from sugar.activity import activity
+
+class MusicpainterActivity(activity.Activity):
+ def __init__(self, handle):
+ activity.Activity.__init__(self, handle)
+ self.connect('destroy', self._cleanup_cb)
+
+ #load the sugar toolbar
+ toolbox = activity.ActivityToolbox(self)
+ self.set_toolbox(toolbox)
+
+ activity_toolbar = toolbox.get_activity_toolbar()
+ activity_toolbar.remove(activity_toolbar.share)
+ activity_toolbar.share = None
+ activity_toolbar.keep.connect('clicked', self._keep_cb)
+ #activity_toolbar.remove(activity_toolbar.keep)
+ #activity_toolbar.keep = None
+ activity_toolbar.stop.can_focus = True
+ activity_toolbar.keep.can_focus = True
+ #activity_toolbar.keep.grab_focus()
+
+ toolbox.show()
+ activity_toolbar.keep.grab_focus()
+
+ self.gamename = 'Musicpainter'
+ self.set_title("Music Painter")
+
+ # connect to the in/out events
+ self.connect('notify::active', self.onActive)
+ self.connect('focus_in_event', self._focus_in)
+ self.connect('focus_out_event', self._focus_out)
+
+ self.musicpainter = Musicpainter.Musicpainter()
+# self.musicpainter.grab_focus()
+# musicpainter.init_csoundpath(activity.get_bundle_path())
+ presenceService = presenceservice.get_instance()
+ xoOwner = presenceService.get_owner() # get my name
+# self.grab_focus()
+ self.musicpainter.initSugar(self, xoOwner.props.nick)
+ try:
+ print "To load: " + self.to_read
+ self.musicpainter.canvas.canvas_load_journal(self.to_read)
+ print "complete!"
+ except:
+ return
+
+# self.activity_toolbar.share.hide()
+
+ def _keep_cb(self, data=None):
+ print "to keep()"
+ self.musicpainter.canvas.save_file()
+ return
+
+ def _cleanup_cb(self, data=None):
+ return
+
+ def _focus_in(self, event, data=None):
+ return
+
+ def _focus_out(self, event, data=None):
+ return
+
+ def onActive(self, widget = None, event = None):
+ if widget.props.active == False:
+ print "MusicpainterActivity.onActive: to disconnect"
+ self.musicpainter.deactivate()
+ else:
+ print "MusicpainterActivity.onActive: to re-connect"
+ self.musicpainter.reactivate()
+
+ def read_file(self, file_path):
+ '''Read file from Sugar Journal.'''
+ print "read file: " + file_path + " pending"
+ self.to_read = file_path
+ #self.musicpainter.canvas.canvas_load_journal(file_path)
+
+ def write_file(self, file_path):
+ '''Save file on Sugar Journal. '''
+ print "write file: " + file_path
+ self.musicpainter.score.write_journal(file_path)
+ self.metadata['activity'] = self.get_bundle_id()
+ self.metadata['mime_type'] = 'application/x-musicpainter'
diff --git a/ToolbarArea.py b/ToolbarArea.py
new file mode 100644
index 0000000..2e3cf00
--- /dev/null
+++ b/ToolbarArea.py
@@ -0,0 +1,549 @@
+import gtk
+import math
+import cairo
+
+_showDebugMsg = False
+
+class ToolbarArea(gtk.DrawingArea):
+
+ def __init__(self, wid, hei, platform, mp):
+
+ self.platform = platform
+
+ self.main = mp
+ self.width, self.height = wid, hei
+ self.init_data()
+ self.init_graphics()
+
+ gtk.DrawingArea.__init__(self)
+
+ self.set_size_request(self.width, self.height)
+
+ # Event signals
+ self.connect("expose_event", self.expose_event)
+ self.connect("configure_event", self.configure_event)
+ self.connect("enter_notify_event", self.enter_notify_event)
+ self.connect("leave_notify_event", self.leave_notify_event)
+ self.connect("motion_notify_event", self.motion_notify_event)
+ self.connect("button_press_event", self.button_press_event)
+ self.connect("button_release_event", self.button_release_event)
+
+ self.set_events(gtk.gdk.EXPOSURE_MASK
+ | gtk.gdk.ENTER_NOTIFY_MASK
+ | gtk.gdk.LEAVE_NOTIFY_MASK
+ | gtk.gdk.BUTTON_PRESS_MASK
+ | gtk.gdk.BUTTON_RELEASE_MASK
+ | gtk.gdk.POINTER_MOTION_MASK
+ | gtk.gdk.POINTER_MOTION_HINT_MASK)
+
+ def init_data(self):
+
+ canvas_width = self.main.canvas.gridw * self.main.canvas.ngrid_h
+
+ if self.height == 56:
+ self.toolbarw = 44
+ self.icon_set = 40
+# elif self.height == 64:
+# self.toolbarw = 44
+# self.icon_set = 40
+ else:
+ self.toolbarw = 54
+ self.icon_set = 48
+
+ self.cx = (int)(0.09 * self.width)
+ self.cy = 12
+
+ if self.width <= 1199:
+ self.toolbarw = 36
+ self.icon_set = 32
+ self.div1 = 18
+ self.div2 = 24
+ self.div3 = 24
+ self.div4 = 8
+ self.sw = 128
+ self.cy = 16
+ elif self.width <= 1440:
+ self.toolbarw = 44
+ self.icon_set = 40
+ self.div1 = 12
+ self.div2 = 20
+ self.div3 = 20
+ self.div4 = 8
+ self.sw = 128
+ else:
+ self.div1 = 36
+ self.div2 = 36
+ self.div3 = 36
+ self.div4 = 12
+ self.sw = 150
+
+ m = canvas_width - self.div1 - self.div2 - self.div3 - self.div4 - self.sw - self.toolbarw * (8+6+5)
+ if m >= 0:
+ if m < 20:
+ v = (int)(m / 4)
+ self.div1 = self.div1 + v
+ self.div2 = self.div2 + v
+ self.div3 = self.div3 + v
+ self.sw = self.sw + v
+ else:
+ v = (int)(m / 4 - 1)
+ self.div1 = self.div1 + v
+ self.div2 = self.div2 + v
+ self.div3 = self.div3 + v
+ self.div4 = 12
+ self.sw = self.sw + v
+
+# self.div1 = 24
+# self.div2 = 24
+# if self.platform == "windows-1024":
+# self.toolbarw = 44
+# self.cy = 12
+# elif self.platform == "sugar-xo":
+# self.toolbarw = 54
+# self.cy = 6
+# self.div1 = 36
+# self.div2 = 36
+# else: # default
+# self.toolbarw = 36
+# self.cy = 12
+
+ # self.cx = 92
+ self.load_icon = 0
+ self.toolsel = 2
+ self.colorsel = 0
+ self.is_dragging = 0
+
+ self.fix_button = 0
+
+ self.sx = self.cx + self.toolbarw*14 + self.div1 + self.div2 # slider
+ self.sy = self.cy + self.toolbarw/2 + 6
+ self.sval = 0.5
+
+ self.pstate = 0
+ self.fstate = 0
+
+ self.from_start = 0
+ self.loop = 0
+ self.record = 0
+
+ def get_color_attr(self, c):
+ if c == 0: # red
+ return (1, 0.225, 0.225)
+ elif c == 1: # orange
+ return (1, 0.5, 0)
+ elif c == 2: # yellow
+ return (0.975, 0.99, 0.01)
+ elif c == 3: # light green
+ return (0.635, 0.97, 0.01)
+ elif c == 4: # dark green
+ return (0.15, 0.6, 0.07)
+ elif c == 5: # light blue
+ return (0, 1, 1)
+ elif c == 6: # blue
+ return (0, 0.02, 0.875)
+ else: # purple
+ return (0.6, 0.15, 1)
+
+ def init_graphics(self):
+ self.light_grey = gtk.gdk.Color(58112,58112,58112)
+ self.dark_grey = gtk.gdk.Color(40960,40960,40960)
+ self.white = gtk.gdk.color_parse('white')
+ self.black = gtk.gdk.color_parse('black')
+ self.blue = gtk.gdk.Color(0,1280,57600)
+ self.green = gtk.gdk.Color(9728,38912,4608)
+ self.red = gtk.gdk.Color(65535,15000,15000)
+ self.yellow = gtk.gdk.Color(64000, 65000, 500)
+ self.purple = gtk.gdk.color_parse('purple')
+ self.orange = gtk.gdk.color_parse('orange')
+ self.lblue = gtk.gdk.Color(0, 65535, 65535)
+ self.grass = gtk.gdk.Color(41728, 63744, 512)
+
+ self.color_list = [self.red,self.orange,self.yellow,self.grass,self.green,self.lblue,self.blue,self.purple]
+
+ def request_tempo_change(self):
+ self.main.score.tempoChange(self.sval)
+
+ def enter_notify_event(self, widget, event):
+ if _showDebugMsg:
+ print "toolbar.enter"
+ self.main.cursor_area = 1
+ self.main.grab_focus()
+
+ def leave_notify_event(self, widget, event):
+ if _showDebugMsg:
+ print "toolbar.leave"
+ if self.main.cursor_area == 1:
+ self.main.cursor_area = 0
+
+ def button_press_event(self, widget, event):
+ if _showDebugMsg:
+ print "toolbar.mouse_btn_press (%d,%d)" % (event.x, event.y)
+ self.fix_button = self.fix_button + 1
+ if self.fix_button != 1:
+ return
+ if event.button == 1:
+ t = self.toolbar_sel(event.x, event.y)
+ if t == -1:
+ t = self.is_dragging_slider(event.x, event.y)
+ if t != -1:
+ self.is_dragging = 1
+ if self.update_slider_val(event.x):
+ self.request_tempo_change()
+ return
+ elif t < 6:
+ flag = 0
+ if self.toolsel == t - 1:
+ if self.toolsel == -1:
+ self.pstate = (self.pstate + 1)%3
+ flag = 1
+ elif self.toolsel == 0:
+ self.fstate = (self.fstate + 1)%3
+ flag = 1
+ else:
+ self.toolsel = t - 1
+ flag = 1
+ if self.toolsel != 1 and self.main.score.select_state == 1:
+ self.main.score.de_selection()
+ self.main.canvas.draw_deselection()
+ if flag == 1:
+ cr = self.pixmap.cairo_create()
+ self.update_toolsel(widget, cr)
+ self.gupdate(widget)
+ elif t < 14:
+ self.select_instrument(t-6)
+ else:
+ if t == 14:
+ self.from_start = (self.from_start + 1) % 2
+ elif t == 15:
+ self.loop = (self.loop + 1) % 2
+ elif t == 16:
+ self.record = (self.record + 1) % 2
+ if self.record == 1 and self.from_start == 0:
+ self.from_start = 1
+ elif t == 17:
+ self.main.score.stop_music(self.main.csound)
+ elif t == 18:
+ self.main.score.play_music(self.main.csound)
+ self.update()
+
+ def select_instrument(self, sel):
+
+ self.main.score.keyboard_change_instrument(self.main.csound, self.colorsel)
+ self.colorsel = sel
+ self.toolsel = 2
+ self.update()
+
+ if not self.main.canvas.is_rec():
+ self.main.score.note_on(self.main.csound, self.colorsel+1, 60, 1)
+ self.main.canvas.update_top()
+
+ def update(self):
+ cr = self.pixmap.cairo_create()
+ widget = self.widget
+ self.update_toolsel(widget, cr)
+ widget.window.draw_drawable(widget.get_style().fg_gc[gtk.STATE_NORMAL], self.pixmap, 0, 0, 0, 0, self.width, self.height)
+
+ def button_release_event(self, widget, event):
+ if _showDebugMsg:
+ print "toolbar.mouse_btn_release (%d,%d)" % (event.x, event.y)
+ self.fix_button = 0
+ if self.is_dragging == 1:
+ self.is_dragging = 0
+ if self.update_slider_val(event.x):
+ self.request_tempo_change()
+ self.deactiviate_slider_btn()
+ return
+
+ def configure_event(self, widget, event):
+ x, y, width, height = widget.get_allocation()
+ self.pixmap = gtk.gdk.Pixmap(widget.window, width, height)
+ return True
+
+ def motion_notify_event(self, widget, event):
+# print "toolbar.mouse_move (%d,%d)" % (event.x, event.y)
+ if self.is_dragging == 1:
+ if self.update_slider_val(event.x):
+ self.request_tempo_change()
+ return
+
+ def expose_event(self, widget, event):
+ cr = self.pixmap.cairo_create()
+ self.widget = widget
+
+ # set a clip region for the expose event
+ x , y, width, height = event.area
+ cr.rectangle(x, y, width, height)
+ cr.clip()
+ self.draw(widget, cr)
+
+ widget.window.draw_drawable(widget.get_style().fg_gc[gtk.STATE_NORMAL], self.pixmap, x, y, x, y, width, height)
+
+ return False
+
+ def gupdate(self, widget):
+ widget.window.draw_drawable(widget.get_style().fg_gc[gtk.STATE_NORMAL], self.pixmap, 0, 0, 0, 0, self.width, self.height)
+
+ def draw_toolbar_frame(self, widget, x, y):
+
+ self.pixmap.draw_rectangle(widget.get_style().white_gc,False,x,y,self.toolbarw,self.toolbarw)
+ gc = self.pixmap.new_gc()
+ gc.set_rgb_fg_color(self.dark_grey)
+ self.pixmap.draw_line(gc, x+1, y+1, x+self.toolbarw-1, y+1)
+ self.pixmap.draw_line(gc, x+1, y+1, x+1, y+self.toolbarw-1)
+ gc.set_rgb_fg_color(self.light_grey)
+ self.pixmap.draw_line(gc, x+self.toolbarw-1, y+2, x+self.toolbarw-1, y+self.toolbarw-1)
+ self.pixmap.draw_line(gc, x+2, y+self.toolbarw-1, x+self.toolbarw-1, y+self.toolbarw-1)
+ self.pixmap.draw_line(widget.get_style().black_gc, x+2, y+2, x+self.toolbarw-2, y+2)
+ self.pixmap.draw_line(widget.get_style().black_gc, x+2, y+2, x+2, y+self.toolbarw-2)
+
+ def load_icons(self, cr):
+ if self.icon_set == 48:
+ self.iconff = cairo.ImageSurface.create_from_png("icon/forte48.png");
+ self.iconpp = cairo.ImageSurface.create_from_png("icon/piano48.png");
+ self.iconf = cairo.ImageSurface.create_from_png("icon/frame48.png");
+ self.icone = cairo.ImageSurface.create_from_png("icon/eraser48.png");
+ self.iconp = cairo.ImageSurface.create_from_png("icon/pencil48.png");
+ self.iconh = cairo.ImageSurface.create_from_png("icon/hand48.png");
+ self.icons = cairo.ImageSurface.create_from_png("icon/scissor48.png");
+ self.iconcresc = cairo.ImageSurface.create_from_png("icon/cresc48.png");
+ self.icondim = cairo.ImageSurface.create_from_png("icon/dim48.png");
+ self.iconfff = cairo.ImageSurface.create_from_png("icon/fortef48.png");
+ self.iconppf = cairo.ImageSurface.create_from_png("icon/pianof48.png");
+ self.iconfst = cairo.ImageSurface.create_from_png("icon/fstart48.png");
+ self.iconpl = cairo.ImageSurface.create_from_png("icon/play48.png");
+ self.iconpla = cairo.ImageSurface.create_from_png("icon/play48g.png");
+ self.iconst = cairo.ImageSurface.create_from_png("icon/stop48.png");
+ self.iconlp = cairo.ImageSurface.create_from_png("icon/loop48.png");
+ self.iconre = cairo.ImageSurface.create_from_png("icon/metro48.png");
+# self.iconre = cairo.ImageSurface.create_from_png("icon/record48.png");
+ elif self.icon_set == 40:
+ self.iconff = cairo.ImageSurface.create_from_png("icon/forte40.png");
+ self.iconpp = cairo.ImageSurface.create_from_png("icon/piano40.png");
+ self.iconf = cairo.ImageSurface.create_from_png("icon/frame40.png");
+ self.icone = cairo.ImageSurface.create_from_png("icon/eraser40.png");
+ self.iconp = cairo.ImageSurface.create_from_png("icon/pencil40.png");
+ self.iconh = cairo.ImageSurface.create_from_png("icon/hand40.png");
+ self.icons = cairo.ImageSurface.create_from_png("icon/scissor40.png");
+ self.iconcresc = cairo.ImageSurface.create_from_png("icon/cresc40.png");
+ self.icondim = cairo.ImageSurface.create_from_png("icon/dim40.png");
+ self.iconfff = cairo.ImageSurface.create_from_png("icon/fortef40.png");
+ self.iconppf = cairo.ImageSurface.create_from_png("icon/pianof40.png");
+ self.iconfst = cairo.ImageSurface.create_from_png("icon/fstart40.png");
+ self.iconpl = cairo.ImageSurface.create_from_png("icon/play40.png");
+ self.iconpla = cairo.ImageSurface.create_from_png("icon/play40g.png");
+ self.iconst = cairo.ImageSurface.create_from_png("icon/stop40.png");
+ self.iconlp = cairo.ImageSurface.create_from_png("icon/loop40.png");
+ self.iconre = cairo.ImageSurface.create_from_png("icon/metro40.png");
+# self.iconre = cairo.ImageSurface.create_from_png("icon/record40.png");
+ else: # icon_set = 32
+ self.iconff = cairo.ImageSurface.create_from_png("icon/forte.png");
+ self.iconpp = cairo.ImageSurface.create_from_png("icon/piano.png");
+ self.iconf = cairo.ImageSurface.create_from_png("icon/frame.png");
+ self.icone = cairo.ImageSurface.create_from_png("icon/eraser.png");
+ self.iconp = cairo.ImageSurface.create_from_png("icon/pencil.png");
+ self.iconh = cairo.ImageSurface.create_from_png("icon/hand.png");
+ self.icons = cairo.ImageSurface.create_from_png("icon/scissor.png");
+ self.iconcresc = cairo.ImageSurface.create_from_png("icon/cresc.png");
+ self.icondim = cairo.ImageSurface.create_from_png("icon/dim.png");
+ self.iconfff = cairo.ImageSurface.create_from_png("icon/fortef.png");
+ self.iconppf = cairo.ImageSurface.create_from_png("icon/pianof.png");
+ self.iconfst = cairo.ImageSurface.create_from_png("icon/fstart32.png");
+ self.iconpl = cairo.ImageSurface.create_from_png("icon/play32.png");
+ self.iconpla = cairo.ImageSurface.create_from_png("icon/play32g.png");
+ self.iconst = cairo.ImageSurface.create_from_png("icon/stop32.png");
+ self.iconlp = cairo.ImageSurface.create_from_png("icon/loop32.png");
+ self.iconre = cairo.ImageSurface.create_from_png("icon/metro32.png");
+# self.iconre = cairo.ImageSurface.create_from_png("icon/record32.png");
+
+
+ self.iconlist = [self.iconf, self.iconp, self.icone, self.icons]
+ self.piconlist = [self.iconpp, self.iconppf, self.icondim]
+ self.ficonlist = [self.iconff, self.iconfff, self.iconcresc]
+ self.pb_iconlist = [self.iconfst, self.iconlp, self.iconre, self.iconst, self.iconpl]
+
+ self.load_icon = 1
+
+ def draw_toolbar_icon(self, widget, cr, x, y, img):
+ self.draw_toolbar_frame(widget, x, y)
+ cr.set_source_surface(img, x+3, y+3)
+ cr.paint()
+
+ def draw_toolbar_colorgrid(self, widget, cr, x, y, color, icon = 0):
+ if icon == 1:
+ if self.toolsel >= 1:
+ self.draw_toolbar_icon(widget, cr, x, y, self.iconlist[self.toolsel-1])
+ elif self.toolsel == 0:
+ self.draw_toolbar_icon(widget, cr, x, y, self.ficonlist[self.fstate])
+ else:
+ self.draw_toolbar_icon(widget, cr, x, y, self.piconlist[self.pstate])
+ else:
+ self.draw_toolbar_frame(widget, x, y)
+
+ c1, c2, c3 = self.get_color_attr(color)
+ if icon == 1:
+ cr.set_source_rgba(c1, c2, c3, 0.6)
+ else:
+ cr.set_source_rgb(c1, c2, c3)
+ cr.rectangle(x+3, y+3, self.toolbarw-4, self.toolbarw-4)
+ cr.fill()
+
+ def draw_slider_btn(self, cr, x, y, len, v):
+ xc = v * (len-10) + x + 5
+ if self.is_dragging:
+ cr.set_source_rgb(0.95, 0.33, 0.33)
+ else:
+ cr.set_source_rgb(0.9, 0.9, 0.9)
+ cr.rectangle(xc - 5, y - 8, 10, 20)
+ cr.fill_preserve()
+
+ cr.set_source_rgb(0.2, 0.7, 0.1)
+ cr.set_line_width(1.2)
+ cr.stroke()
+
+ def draw_slider(self, cr, x, y, len, v):
+ cr.set_source_rgb(0.84, 0.84, 1)
+ cr.rectangle(x-2, y-24, len + 4, 38)
+ cr.fill()
+
+ cr.set_source_rgb(0.7, 0.7, 0.7)
+ cr.rectangle(x, y, len, 5)
+ cr.fill_preserve()
+
+ cr.set_source_rgb(0, 0, 0)
+ cr.set_line_width(0.5)
+ cr.stroke()
+
+ self.draw_slider_btn(cr, x, y, len, v)
+ self.draw_slider_text(cr, x, y, len)
+
+ def draw_slider_text(self, cr, x, y, len):
+ if self.platform == "sugar-xo":
+ cr.set_font_size(16)
+ cr.set_source_rgb(0.4, 0.4, 0.4)
+ cr.move_to(x, y - 14)
+ cr.show_text("Slow")
+ cr.move_to(x + len - 30, y - 14)
+ cr.show_text("Fast")
+ else:
+ cr.set_font_size(12)
+ cr.set_source_rgb(0.4, 0.4, 0.4)
+ cr.move_to(x, y - 12)
+ cr.show_text("Slow")
+ cr.move_to(x + len - 25, y - 12)
+ cr.show_text("Fast")
+
+ def is_dragging_slider(self, x, y):
+ x0 = self.sval * (self.sw-10) + self.sx
+ y0 = self.sy - 8
+ x1 = x0 + 10
+ y1 = y0 + 20
+
+ if y0 > y or y >= y1 or self.sx > x or x >= self.sx + self.sw:
+ return -1
+ if y0 <= y and y < y1 and x0 <= x and x < x1:
+ return 1
+ return 0
+
+ def deactiviate_slider_btn(self):
+ cr = self.pixmap.cairo_create()
+ self.draw_slider(cr, self.sx, self.sy, self.sw, self.sval)
+ self.gupdate(self.widget)
+
+ def change_slider_val(self, d):
+ ov = self.sval
+ self.sval = self.sval + d
+ if self.sval < 0:
+ self.sval = 0
+ elif self.sval > 1:
+ self.sval = 1
+ if ov == self.sval:
+ return False
+
+ if _showDebugMsg:
+ print "slider value = %.2f" % self.sval
+ cr = self.pixmap.cairo_create()
+ self.draw_slider(cr, self.sx, self.sy, self.sw, self.sval)
+ self.gupdate(self.widget)
+ return True
+
+ def update_slider_val(self, x):
+ x0 = self.sx + 5
+ x1 = self.sx + self.sw - 5
+ ov = self.sval
+ if x > x1:
+ self.sval = 1
+ elif x < x0:
+ self.sval = 0
+ else:
+ self.sval = 1.0*(x - x0)/(x1 - x0)
+ if ov == self.sval:
+ return False
+
+ if _showDebugMsg:
+ print "slider value = %.2f" % self.sval
+ cr = self.pixmap.cairo_create()
+ self.draw_slider(cr, self.sx, self.sy, self.sw, self.sval)
+ self.gupdate(self.widget)
+ return True
+
+ def toolbar_sel(self, x, y):
+ if y < self.cy or y >= self.cy + self.toolbarw:
+ return -1
+ if x >= self.cx and x < self.cx + self.toolbarw*6:
+ return (int)((x-self.cx)/self.toolbarw)
+ if x < self.cx + self.toolbarw*6 + self.div1:
+ return -1
+ t = (int)((x-self.cx-self.toolbarw*6-self.div1)/self.toolbarw)
+ if t >= 8:
+ if x < self.cx + self.toolbarw*14 + self.div1 + self.div2 + self.sw + self.div3:
+ return -1
+ t = (int)((x-self.cx-self.toolbarw*14-self.div1-self.div2-self.div3-self.sw)/self.toolbarw)
+ if t >= 3:
+ t = (int)((x-self.cx-self.toolbarw*17-self.div1-self.div2-self.div3-self.sw-self.div4)/self.toolbarw)
+ if t >= 2:
+ return -1
+ return t + 17
+ return t+14
+ return t+6
+
+ def update_toolsel(self, widget, cr):
+ for i in range(8):
+ self.draw_toolbar_colorgrid(widget, cr, self.cx + self.toolbarw*(i+6) + self.div1, self.cy, i, (i == self.colorsel and self.toolsel == 2))
+
+ for i in range(6):
+ if i == 0:
+ self.draw_toolbar_icon(widget, cr, self.cx + self.toolbarw*i, self.cy, self.piconlist[self.pstate])
+ elif i == 1:
+ self.draw_toolbar_icon(widget, cr, self.cx + self.toolbarw*i, self.cy, self.ficonlist[self.fstate])
+ else:
+ self.draw_toolbar_icon(widget, cr, self.cx + self.toolbarw*i, self.cy, self.iconlist[i-2])
+
+ c1, c2, c3 = self.get_color_attr(0)
+ for i in range(5):
+ x = self.cx + self.toolbarw*14 + self.div1 + self.div2 + self.sw + self.div3 + i*self.toolbarw
+ if i >= 3:
+ x += self.div4
+ if i == 4 and self.main.score.play_state != -2:
+ self.draw_toolbar_icon(widget, cr, x, self.cy, self.iconpla)
+ else:
+ self.draw_toolbar_icon(widget, cr, x, self.cy, self.pb_iconlist[i])
+ if i == 0 and self.from_start == 1 or i == 1 and self.loop == 1 or i == 2 and self.record == 1:
+ cr.set_source_rgba(c1, c2, c3, 0.4)
+ cr.rectangle(x+3, self.cy+3, self.toolbarw-6, self.toolbarw-6)
+ cr.fill()
+
+ c1, c2, c3 = self.get_color_attr(self.colorsel)
+ cr.set_source_rgba(c1, c2, c3, 0.4)
+ cr.rectangle(self.cx + self.toolbarw*(self.toolsel+1) +3, self.cy +3, self.toolbarw-6, self.toolbarw-6)
+ cr.fill()
+
+ def draw(self, widget, cr):
+ cr.set_source_rgb(0.84,0.84,1)
+ cr.rectangle(0, 0, self.width, self.height)
+ cr.fill()
+
+ if self.load_icon == 0:
+ self.load_icons(cr)
+ self.update_toolsel(widget, cr)
+
+ self.draw_slider(cr, self.sx, self.sy, self.sw, self.sval)
diff --git a/checkVersion.py b/checkVersion.py
new file mode 100644
index 0000000..6396e03
--- /dev/null
+++ b/checkVersion.py
@@ -0,0 +1,49 @@
+from ftplib import FTP
+
+stream = open("version.txt", 'r')
+
+def writeline_cb(line):
+ stream.writelines(line + "\n")
+
+if __name__ == "__main__":
+
+ line1 = stream.readline().replace("\n","")
+ stream.close()
+
+ try:
+ stream3 = open("musicpainter.config", 'r')
+ username = stream3.readline().replace("\n","")
+ ip = stream3.readline().replace("\n","")
+ stream3.close()
+ except:
+ username = "Guest"
+ ip = "musicpainter.media.mit.edu"
+
+ ftp = FTP(ip, "musicpainter", "medialab")
+ stream2 = open("srv_version.txt",'w')
+ ftp.retrlines("RETR src/version.txt", stream2.writelines)
+ stream2.close()
+
+ stream2 = open("srv_version.txt",'r')
+ line2 = stream2.readline().replace("\n","")
+ stream2.close()
+
+ if line1 == line2:
+ print "You're using the latest version!"
+ else:
+ print "Start downloading the latest version!"
+ stream4 = open("blank.sco", 'r')
+ log = username + "_update_version.log"
+ ftp.storlines("STOR log/" + log, stream4)
+ stream4.close()
+
+ list = ftp.nlst("src/*.*")
+ for i in range(len(list)):
+ stream = open(list[i], 'w')
+ msg = ftp.retrlines("RETR src/" + list[i], writeline_cb)
+ print "Downloading " + list[i] + "...." + msg
+ stream.close()
+ print "You're using the latest version!"
+# except:
+# print "Ignore update"
+ ftp.quit()
diff --git a/codes.py b/codes.py
new file mode 100644
index 0000000..608af2f
--- /dev/null
+++ b/codes.py
@@ -0,0 +1,78 @@
+# Codes used for interpreting messages from CsoundXO to Python
+
+CONNECTED= 1
+NEW_INST= 2
+ORCFIL= 3
+SCOFIL= 4
+MIDFIL= 5
+ORCSTR= 6
+SCOSTR= 7
+SET_ALIAS= 8
+GET_ALIAS= 9
+SET_VOLUME= 10
+GET_VOLUME= 11
+SET_MAS_VOL= 12
+GET_MAS_VOL= 13
+SET_TEMPO= 14
+GET_TEMPO= 15
+SET_MIDISPEED= 16
+GET_MIDISPEED= 17
+SET_MSGLEVEL= 18
+GET_MSGLEVEL= 19
+SET_DISPLAYS= 20
+SET_GRAPHICS= 21
+BEAT_EVT= 22
+LINE_EVT= 23
+CLR_LINES= 24
+UL_BEAT= 25
+WAITON_END= 26
+
+SVOPEN= 40
+INSREMOTE= 41
+INSGLOBAL= 42
+MIDIREMOTE= 43
+MIDIGLOBAL= 44
+AUDREMOTE_SI= 45
+AUDGLOBAL_SI= 46
+AUDREMOTE_SO= 47
+AUDGLOBAL_SO= 48
+
+XTRA_SCOREVT= 51
+XTRA_MIDINOTEON= 52
+XTRA_MIDINOTEOFF= 53
+XTRA_MIDIEVT= 54
+XTRA_MIDIMSG= 55
+XTRA_SYSEXMSG= 56
+XTRA_AUDBUF_SI= 57
+XTRA_AUDBUF_SO= 58
+
+NET_STATS= 61
+PRINT_STATS= 62
+ECHO= 63
+
+IOBUFFRAMES= 74
+BUFTIMER= 75
+P2TIMER= 76
+OMAXLAGG= 77
+INNAME= 78
+OUTNAME= 79
+INTAUDIO= 80
+PREP= 81
+PLAY= 82
+PLAY_FOR_TIME= 83
+PAUSE= 84
+RESUME= 85
+PLAYALL= 86
+PLAYALL_FOR_TIME= 87
+PAUSEALL= 88
+RESUMEALL= 89
+REWIND1= 90
+REWINDALL= 91
+FASTFWD_FOR_TIME= 92
+FASTFWD_TO_TIME= 93
+DEACTIVATE= 94
+REACTIVATE= 95
+RELEASE_INST= 96
+CL_DISCONNECT= 97
+SV_CLOSEIO= 98
+SV_SHUTDOWN= 99
diff --git a/setup.py b/setup.py
new file mode 100644
index 0000000..ec0f64e
--- /dev/null
+++ b/setup.py
@@ -0,0 +1,3 @@
+#!/usr/bin/env python
+from sugar.activity import bundlebuilder
+bundlebuilder.start()