From d01c66e757b835f5feba0f995694f0f9fc5cb630 Mon Sep 17 00:00:00 2001 From: Wu-Hsi Li Date: Sun, 02 Mar 2014 07:30:35 +0000 Subject: init commit --- 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() -- cgit v0.9.1