def __init__(self): reload(sys) sys.setdefaultencoding('UTF-8') self.datatype = 'main' self.title = 'NetEase Music' self.datalist = ['Ranking', 'Artist', 'Mew', 'Feature', 'Mine', 'Broadcast', 'DJing', 'Collection', 'Search', 'Help'] self.offset = 0 self.index = 0 self.presentsongs = [] self.player = Player() self.ui = Ui() self.netease = NetEase() self.screen = curses.initscr() self.screen.keypad(1) self.step = 10 self.stack = [] self.djstack = [] self.userid = None self.username = None try: sfile = file(home + "/netease-musicbox/flavor.json", 'r') data = json.loads(sfile.read()) self.collection = data['collection'] self.account = data['account'] sfile.close() except: self.collection = [] self.account = {}
def main(): #Datastructure for faces and names fd = FaceData() rec = Recognition() root = Tk() ui = Ui(root, fd) def task(): #while True: #print("length: "+ str(len(known_face_names))) rec.find_faces(fd) ui.updateList() ## TODO: Hit 'q' on the keyboard to quit! if cv2.waitKey(1) & 0xFF == ord('q'): print("q pressed") # break root.after(20, task) # reschedule event in 2 seconds root.after(20, task) ui.startLoop() rec.close()
def __init__(self): reload(sys) sys.setdefaultencoding('UTF-8') self.datatype = 'main' self.title = '网易云音乐' self.datalist = [ '排行榜', '艺术家', '新碟上架', '精选歌单', '我的歌单', 'DJ节目', '打碟', '收藏', '搜索', '帮助' ] self.offset = 0 self.index = 0 self.presentsongs = [] self.player = Player() self.ui = Ui() self.netease = NetEase() self.screen = curses.initscr() self.screen.keypad(1) self.step = 10 self.stack = [] self.djstack = [] self.userid = None self.username = None signal.signal(signal.SIGWINCH, self.change_term) signal.signal(signal.SIGINT, self.send_kill) try: sfile = file(Constant.conf_dir + "/flavor.json", 'r') data = json.loads(sfile.read()) self.collection = data['collection'] self.account = data['account'] sfile.close() except: self.collection = [] self.account = {}
def __init__(self, surface: Surface, dialog_font: Font, choice_font: Font, images: Dict[str, Surface], animations: Dict[str, List[Surface]], sound_player: SoundPlayer, dialog_graph: DialogGraph, picture_size: Vec2, select_blip_sound_id: str): self._validate_inputs(dialog_graph, images, sound_player) self.surface = surface self._sound_player = sound_player self._dialog_graph = dialog_graph self._current_dialog_node = self._dialog_graph.current_node() background_id = self._dialog_graph.background_image_id background = images[background_id] if background_id else None self._ui = Ui(surface=surface, picture_size=picture_size, dialog_node=self._current_dialog_node, dialog_font=dialog_font, choice_font=choice_font, images=images, animations=animations, sound_player=sound_player, background=background, select_blip_sound_id=select_blip_sound_id) self._play_dialog_sound()
def log_in(cls): ''' Handles logging in as user based on given email and password. Redirects to specific submenu. ''' login = Ui.get_inputs(['Please enter your email: '], "") password = [] passw = getpass.getpass('Enter pass: '******'Invalid login or password. Please try again. ') elif user: os.system('clear') Ui.print_message('\nHello, ' + user.name + '!\n') time.sleep(2) if user.status == 'manager': Menu.loading_data() ManagerMenu.handle_menu(user) elif user.status == 'employee': Menu.loading_data() EmployeeMenu.handle_menu(user) elif user.status == 'mentor': Menu.loading_data() MentorMenu.handle_menu(user) elif user.status == 'student': Menu.loading_data() StudentMenu.handle_menu(user) return None
def init_game(self): self.board, _ = engine.new_game(cols, rows) self.new_stone() self.level = 1 self.score = 0 self.lines = 0 Ui.set_timer(1000)
def show_full_report_of_students_performance(): """ method asks for input to get specific date, and creates a list of students performance in specific period of time """ os.system('clear') st_end_date = Ui.get_inputs( ['Start date (yyyy-mm-dd): ', 'End date (yyyy-mm-dd): '], "Type the values") list_of_performance = [] conn = sqlite3.connect("database.db") with conn: c = conn.cursor() db = c.execute( "SELECT submission.send_date, submission.name, student.name, student.surname, submission.grade\ FROM submission\ INNER JOIN student\ ON submission.student_id=student.student_id\ WHERE submission.send_date BETWEEN (?) AND (?)\ ORDER BY student.surname ASC;", (st_end_date[0], st_end_date[1])) conn.commit() for row in db: list_of_performance.append(row) title_of_table = 'FULL REPORT OF STUDENTS PERFORMANCE:' top_of_table = ('SUB. SEND DATE', 'SUB. NAME', 'STUDENT NAME', 'SURNAME', 'GRADE') Ui.print_full_report_of_students_performance(list_of_performance, title_of_table, top_of_table)
def intentar_letra(self, partida, letra): print('Turno jugador 1: ' + partida._nombre_jugador) for x in range(len(partida.palabra)): if partida._intentos == 0: raise ValueError if letra == partida.palabra[x]: print('Bien!') partida.palabra_aciertos[x] = partida.palabra[x] if partida.palabra == partida.palabra_aciertos: StrA = "".join(partida._palabra) print(StrA) return 'Gano' partida._intentos -= 1 Ui.salto(self) print('Intentos: ' + str(partida._intentos)) print('Tipo de palabra: ' + partida._tipo_palabra) print('Letra adivindadas : ' + str(partida._palabra_aciertos)) if partida._intentos == 0: return 'Perdio' if partida._intentos > 0 and partida.palabra_aciertos != partida.palabra: return 'Continua'
def effect(self): """If there is an original element, store it. Open the GUI.""" self.orig, self.orig_src = self.get_original() self.ui = Ui(self.render, self.orig_src, self.get_settings()) self.ui.main()
def __init__(self, app, loop, engine): super().__init__() self.app = app self.loop = loop self.engine = engine self.timers = {} self.event_bus = EventBus(loop, self) self.ui = Ui() self.ui.show() self.ui.shortcut_close.activated.connect(self.close_app) self.ui.decks[0].play_pause.connect(self.play_pause_clicked) self.ui.decks[1].play_pause.connect(self.play_pause_clicked) self.ui.decks[0].tempo_changed.connect(self.tempo_changed) self.ui.decks[1].tempo_changed.connect(self.tempo_changed) self.ui.cross_fader.valueChanged.connect(self.cross_fade) self.social_controller = SocialController(self, self.ui) self.library_controller = LibraryController(self, self.ui)
def __init__(self): reload(sys) sys.setdefaultencoding('UTF-8') self.config = Config() self.datatype = 'main' self.title = '网易云音乐' self.datalist = [ '排行榜', '艺术家', '新碟上架', '精选歌单', '我的歌单', 'DJ节目', '每日推荐', '私人FM', '搜索', '帮助' ] self.offset = 0 self.index = 0 self.storage = Storage() self.storage.load() self.collection = self.storage.database['collections'][0] self.player = Player() self.cache = Cache() self.ui = Ui() self.netease = NetEase() self.screen = curses.initscr() self.screen.keypad(1) self.step = 10 self.stack = [] self.djstack = [] self.userid = self.storage.database["user"]["user_id"] self.username = self.storage.database["user"]["nickname"] self.resume_play = True self.at_playing_list = False signal.signal(signal.SIGWINCH, self.change_term) signal.signal(signal.SIGINT, self.send_kill) self.START = time.time()
def show_mentors(): ''' Prepares data to display in a formatted table. ''' title = 'Mentors list:' title_list = ['ID', 'Name', 'Surname', 'Email', 'Status'] table = Ui.create_person_table_to_print(Mentor.mentors_list) Ui.print_table(table, title, title_list)
def show_regular_employees(): ''' Prepares data to display in a formatted table. ''' title = 'Regular employees list:' title_list = ['ID', 'Name', 'Surname', 'Email', 'Status'] table = Ui.create_person_table_to_print(Employee.employees_list) Ui.print_table(table, title, title_list)
def show_students_data(): ''' Prepares data to display in a formatted table. ''' title_list = ['ID', 'Name', 'Surname', 'Email', 'Status', 'Team', 'Card'] title = 'Student list:' table = Ui.create_student_table_to_print(Student.student_list) Ui.print_table(table, title, title_list)
def run(): try: ui = Ui() except ValueError as ve: print(ve) return ui.run()
def show_students(): ''' Prepares data to display in a formatted table. ''' title = 'Student list:' title_list = ['ID', 'Name', 'Surname', 'Email', 'Status'] table = Ui.create_person_table_to_print(Student.student_list) Ui.print_table(table, title, title_list) Ui.get_inputs([''], "Click enter to go back")
def add_cl_lines(self, n): linescores = [0, 40, 100, 300, 1200] self.lines += n self.score += linescores[n] * self.level if self.lines >= self.level*6: self.level += 1 newdelay = 1000-50*(self.level-1) newdelay = 100 if newdelay < 100 else newdelay Ui.set_timer(newdelay)
def __init__(self): Ui.initialise(self) self.width = cell_size*(cols+6) self.height = cell_size*rows self.rlim = cell_size*cols self.bground_grid = [[ 8 if x%2==y%2 else 0 for x in range(cols)] for y in range(rows)] self.screen = Ui.get_screen(self.width, self.height) self.next_stone = engine.get_new_piece() self.init_game()
def __init__(self, board: Board, cell_size): self._board = board self._ui = Ui(cell_size, self._board) self._new_generation_delay = 100 self._quit = False self._generation_update_enabled = False # Mouse motions would trigger unnecessary redraw events very frequently pygame.event.set_blocked(pygame.MOUSEMOTION)
def __init__(self): self.ui = Ui() self.datatype = 'songs' self.popen_handler = None # flag stop, prevent thread start self.playing_flag = False self.pause_flag = False self.songs = [] self.idx = 0
def show_grades(user): ''' Prepares data to display in a formatted table. ''' submissions = user.view_grades() table = Ui.create_submission_table_to_print(submissions) title = ('\nYour submissions:\n') title_list = ['Submission name', 'Grade'] Ui.print_table(table, title, title_list)
def main(): os.system('clear') Menu.loading_people() while True: Menu.main_menu() try: Menu.choose_option() except KeyError: Ui.print_message('Unknown error at main!')
def __create_and_init_UI(self): """[summary] """ self.POSTAGE_SERVICE_UI = wx.App() self.FRAME = Ui(self.name, parent=None, id=-1, app=self) self.FRAME.Centre() self.FRAME.Show() self.POSTAGE_SERVICE_UI.MainLoop()
def show_attendance(user): ''' Prepares data to display in a formatted table. ''' data = Attendance.attendances_list table = user.check_attendence(data) title = 'Your attendance' title_list = ['Date', 'Attendance [%]'] Ui.print_table(table, title, title_list)
def __init__(self, width, height, display): self.width = width self.height = height self.display = display self.SCROLL_X = 400 self.SCROLL_Y = 200 self.x = self.y = 0 self.FLOOR_Y_LEVEL = 380 self.MAX_X = 5000 self.MAX_Y = 5000 self.slow_time = -1 self.all_sprites = pygame.sprite.Group() self.all_game_objects = pygame.sprite.Group() self.background = pygame.sprite.Group() self.platforms = pygame.sprite.Group() self.characters = pygame.sprite.Group() self.projectiles = pygame.sprite.Group() self.foreground = pygame.sprite.Group() self.layers_list = [ self.all_sprites, self.background, self.projectiles, self.platforms, self.characters, self.foreground ] self.collide_with_player = pygame.sprite.Group() self.clock = pygame.time.Clock() self.player_character = Player(50, self.FLOOR_Y_LEVEL - 50, self) self.player_character.add(self.all_sprites, self.all_game_objects, self.characters) self.initialize_level() #texte = "Je crois que les filles m'aiment bien parceque je suis un peu mystérieux comme Light Yagami, je suis toujours tout seul, aux récrées je m’assoie sur un banc avec ma capuche et la tête baissé et quand quelque passe à coté de moi je chuchote des truc genre okamari no suzoki, ça ne veut rien dire mais ça fait mystique, les gens sont intrigués." texte = "Voix dans votre tête : Bonjour. Vous vous réveiller soudainement dans un laboratoire. Vous n’avez rien sur vous, mais soudain vous avez une envie incontrôlable de voler toutes les pièces. <ENTRER>| | (Pour vous déplacer vous pouvez utiliser les flèches du clavier, et la touche espace vous permet de ralentir le temps.) |Bonne chance" self.ui = Ui(self.display, self.width, self.height, 499, 190, 300, 400, texte, self) self.ui.add(self.all_sprites, self.foreground) self.game_song_slow = pygame.mixer.Sound("assets/music1.wav") self.game_song = pygame.mixer.Sound("assets/music0.wav") self.music() self.score = 0 self.fond_image = pygame.transform.scale( pygame.image.load("assets/fond.png"), (800, 350)).convert_alpha() self.game_over_image = pygame.transform.scale( pygame.image.load("assets/gameover.png"), (800, 600)).convert() self.game_victoire_image = pygame.transform.scale( pygame.image.load("assets/victory.png"), (800, 600)).convert()
def add_team(): """ Add a new team. :param input """ os.system("clear") name = Ui.get_inputs(" ", 'Type a name of a new team: \n') Student.teams_list.append(name[0]) wait = Ui.get_inputs(" ", '\nTeam has been added succesfully.\n') os.system("clear")
def show_full_statistics_about_students(): ''' Prepares data to display in a formatted table. ''' data = Submission.get_students_average_grades(Submission.submission_list) average_grades = Submission.get_name_by_id(data, Student.student_list) table = Student.get_full_statistics_about_students(Student.student_list, average_grades) title_list = ['ID', 'Name', 'Surname', 'Email', 'Team', 'Average', 'Card'] title = 'FULL STATISTICS ABOUT STUDENTS' Ui.print_table(table, title, title_list)
def show_average_of_grades(): ''' Prepares data to display in a formatted table. ''' data = Submission.get_students_average_grades(Submission.submission_list) average_grades = Submission.get_name_by_id(data, Student.student_list) title = 'Students average grades' title_list = ['Id', 'Name', 'Surname', 'Average of grades'] table = Ui.create_average_grades_table_to_print(average_grades) Ui.print_table(table, title, title_list)
def view_assignment_list(): """ method prints the list or error_message if list is empty """ if len(Assignments.assignments_list) == 0: Ui.print_message("Assignment list is empty") else: Ui.print_assignments_list(Assignments.assignments_list, "Assignments List:")
def choose_option(cls): ''' Allows user to log in or exit program. ''' inputs = Ui.get_inputs(["Please enter a number: "], "") option = inputs[0] if option == "1": Menu.log_in() elif option == "0": sys.exit(0) else: Ui.print_message('There is no such option.')
def __init__(self): reload(sys) sys.setdefaultencoding('UTF-8') self.config = Config() self.datatype = 'main' self.title = 'NetEase Music' self.datalist = ['Charts', 'Artists', 'New Songs', 'Songs', 'My Songs', 'Radio Stations', 'Recommended', 'Personal Radio', 'Search', 'Help'] self.offset = 0 self.index = 0 self.storage = Storage() self.storage.load() self.collection = self.storage.database['collections'][0] self.player = Player() self.player.playing_song_changed_callback = self.song_changed_callback self.cache = Cache() self.ui = Ui() self.netease = NetEase() self.screen = curses.initscr() self.screen.keypad(1) self.step = 10 self.stack = [] self.djstack = [] self.userid = self.storage.database['user']['user_id'] self.username = self.storage.database['user']['nickname'] self.resume_play = True self.at_playing_list = False signal.signal(signal.SIGWINCH, self.change_term) signal.signal(signal.SIGINT, self.send_kill) self.START = time.time()
def __init__(self): reload(sys) sys.setdefaultencoding('UTF-8') self.datatype = 'main' self.title = '网易云音乐' self.datalist = ['排行榜', '艺术家', '新碟上架', '精选歌单', '我的歌单', 'DJ节目', '打碟', '收藏', '搜索', '帮助'] self.offset = 0 self.index = 0 self.presentsongs = [] self.player = Player() self.ui = Ui() self.netease = NetEase() self.screen = curses.initscr() self.screen.keypad(1) self.step = STEP self.stack = [] self.djstack = [] self.userid = None self.username = None try: sfile = file(home + "/netease-musicbox/flavor.json",'r') data = json.loads(sfile.read()) self.collection = data['collection'] self.account = data['account'] sfile.close() except: self.collection = [] self.account = {}
def __init__(self): reload(sys) sys.setdefaultencoding('UTF-8') self.datatype = 'main' self.title = '网易云音乐' self.datalist = ['排行榜', '艺术家', '新碟上架', '精选歌单', '我的歌单', 'DJ节目', '打碟', '收藏', '搜索', '帮助'] self.offset = 0 self.index = 0 self.presentsongs = [] self.player = Player() self.ui = Ui() self.netease = NetEase() self.screen = curses.initscr() self.screen.keypad(1) self.step = 10 self.stack = [] self.djstack = [] self.userid = None self.username = None self.resume_play = True signal.signal(signal.SIGWINCH, self.change_term) signal.signal(signal.SIGINT, self.send_kill) try: sfile = file(Constant.conf_dir + "/flavor.json", 'r') data = json.loads(sfile.read()) self.collection = data['collection'] self.account = data['account'] self.presentsongs = data['presentsongs'] sfile.close() except: self.collection = [] self.account = {} self.presentsongs = [] self.resume_play = False
def __init__(self): reload(sys) sys.setdefaultencoding('UTF-8') self.config = Config() self.datatype = 'main' self.title = '网易云音乐' self.datalist = ['排行榜', '艺术家', '新碟上架', '精选歌单', '我的歌单', 'DJ节目', '每日推荐', '私人FM', '搜索', '帮助'] self.offset = 0 self.index = 0 self.storage = Storage() self.storage.load() self.collection = self.storage.database['collections'][0] self.player = Player() self.player.playing_song_changed_callback = self.song_changed_callback self.cache = Cache() self.ui = Ui() self.netease = NetEase() self.screen = curses.initscr() self.screen.keypad(1) self.step = 10 self.stack = [] self.djstack = [] self.userid = self.storage.database["user"]["user_id"] self.username = self.storage.database["user"]["nickname"] self.resume_play = True self.at_playing_list = False signal.signal(signal.SIGWINCH, self.change_term) signal.signal(signal.SIGINT, self.send_kill) self.START = time.time()
def __init__(self): reload(sys) sys.setdefaultencoding('UTF-8') self.data_type = 'main' # Title of the application self.title = '网易云音乐' # Main-menu list self.data_list = ['排行榜', '艺术家', '新碟上架', '精选歌单', '我的歌单', 'DJ节目', '打碟', '收藏', '搜索', '帮助'] # Which page of the data_list is displayed (data_list may be displayed in multiple pages self.page_index = 0 # The index of the current selected line self.current_line_index = 0 self.present_songs = [] self.player = Player() self.ui = Ui() self.netease = NetEase() self.screen = curses.initscr() self.screen.keypad(1) self.page_size = 10 # The number of lines that can be displayed on one page. self.stack = [] self.dj_stack = [] self.user_id = None self.user_name = None # Read in the collection and account in flavor.json try: config_file = file(Constant.conf_dir + "/flavor.json", 'r') data = json.loads(config_file.read()) self.collection = data['collection'] self.account = data['account'] config_file.close() except: self.collection = [] self.account = {}
def __init__(self): reload(sys) sys.setdefaultencoding("UTF-8") self.datatype = "main" self.title = "网易云音乐" self.datalist = ["排行榜", "艺术家", "新碟上架", "精选歌单", "我的歌单", "DJ节目", "打碟", "收藏", "搜索", "帮助"] self.offset = 0 self.index = 0 self.storage = Storage() self.storage.load() self.collection = self.storage.database["collections"][0] self.player = Player() self.ui = Ui() self.netease = NetEase() self.screen = curses.initscr() self.screen.keypad(1) self.step = 10 self.stack = [] self.djstack = [] self.userid = None self.username = None self.resume_play = True signal.signal(signal.SIGWINCH, self.change_term) signal.signal(signal.SIGINT, self.send_kill) self.START = time.time()
def __init__(self): reload(sys) sys.setdefaultencoding("UTF-8") self.config = Config() self.datatype = "main" self.title = "网易云音乐" self.datalist = ["排行榜", "艺术家", "新碟上架", "精选歌单", "我的歌单", "DJ节目", "每日推荐", "私人FM", "搜索", "帮助"] self.offset = 0 self.index = 0 self.storage = Storage() self.storage.load() self.collection = self.storage.database["collections"][0] self.player = Player() self.player.playing_song_changed_callback = self.song_changed_callback self.cache = Cache() self.ui = Ui() self.netease = NetEase() self.screen = curses.initscr() self.screen.keypad(1) self.step = 10 self.stack = [] self.djstack = [] self.userid = self.storage.database["user"]["user_id"] self.username = self.storage.database["user"]["nickname"] self.resume_play = True self.at_playing_list = False signal.signal(signal.SIGWINCH, self.change_term) signal.signal(signal.SIGINT, self.send_kill) self.START = time.time()
class Menu(): def __init__(self): reload(sys) sys.setdefaultencoding('utf8') self.const = util.Constant() self.datalist = ['搜索歌曲', '搜索艺术家'] self.datatype = 'main' self.lib = Library() self.offset = 0 self.page = 0 self.player = vlc.VLC() self.START = time.time() self.step = 10 self.title = 'KANraoke' self.screen = curses.initscr() self.ui = Ui() signal.signal(signal.SIGWINCH, self.change_term) signal.signal(signal.SIGINT, self.send_kill) def change_term(self, signum, frame): self.screen.clear() self.screen.refresh() def send_kill(self, signum, fram): curses.endwin() sys.exit() def start(self): self.ui.display_list(self.datatype, self.title, self.datalist, self.offset, self.page, self.step, self.START) while True: self.screen.timeout(500) key = self.screen.getch() # key = self.screen.getkey() # if key != -1: # print key self.screen.refresh() # break # if key == -1: # self.ui.update_size() self.ui.display_list(self.datatype, self.title, self.datalist, self.offset, self.page, self.step, self.START) pass
class InkTex(inkex.Effect): """ Our main class, derived from inkex.Effect. It wraps the other classes and implements the effect() function. """ def __init__(self): inkex.Effect.__init__(self) # the original (i.e., selected) svg element and the newly created one # including the original LaTeX source. self.orig = None self.orig_src = None self.new = None self.new_src = None def effect(self): """If there is an original element, store it. Open the GUI.""" self.orig, self.orig_src = self.get_original() self.ui = Ui(self.render, self.orig_src, self.get_settings()) self.ui.main() def render(self, tex, settings): """Execute the rendering and, upon errors, send them to the UI""" self.new_src = tex self.store_settings(settings) with Converter(self) as renderer: try: self.new = renderer.render(self.new_src, settings) self.copy_styles() self.store_src_information() self.append_or_replace() return True except Exception, e: self.ui.log(e.message)
def __init__(self): self.ui = Ui() self.datatype = 'songs' self.popen_handler = None # flag stop, prevent thread start self.playing_flag = False self.pause_flag = False self.songs = [] self.idx = 0 self.next_music_p=False #播放下一曲标志 self.stop_sub=False #结束自动播放下一曲,手动选择播放`` self.mplayer_controller=os.path.join(tempfile.mkdtemp(),'mplayer_controller') os.mkfifo(self.mplayer_controller) #临时文件``
def __init__(self): self.ui = Ui() self.popen_handler = None # flag stop, prevent thread start self.playing_flag = False self.pause_flag = False self.process_length = 0 self.process_location = 0 self.process_first = False self.storage = Storage() self.info = self.storage.database["player_info"] self.songs = self.storage.database["songs"] self.playing_id = -1
def main(): ui = Ui() details = ui.get_details() status = admin.register(details,ui) if status == True: ui.display( "registration successed") else: ui.display("registration failed")
def __init__(self): self.ui = Ui() self.datatype = 'songs' self.popen_handler = None # flag stop, prevent thread start self.playing_flag = False self.pause_flag = False self.songs = [] self.idx = 0 self.volume = 60 self.process_length = 0 self.process_location = 0 self.process_first = False self.playing_mode = 0
def __init__(self): self.config = Config() self.ui = Ui() self.popen_handler = None # flag stop, prevent thread start self.playing_flag = False self.pause_flag = False self.process_length = 0 self.process_location = 0 self.process_first = False self.storage = Storage() self.info = self.storage.database["player_info"] self.songs = self.storage.database["songs"] self.playing_id = -1 self.cache = Cache() self.mpg123_parameters = self.config.get_item("mpg123_parameters")
def __init__(self): reload(sys) sys.setdefaultencoding('utf8') self.const = util.Constant() self.datalist = ['搜索歌曲', '搜索艺术家'] self.datatype = 'main' self.lib = Library() self.offset = 0 self.page = 0 self.player = vlc.VLC() self.START = time.time() self.step = 10 self.title = 'KANraoke' self.screen = curses.initscr() self.ui = Ui() signal.signal(signal.SIGWINCH, self.change_term) signal.signal(signal.SIGINT, self.send_kill)
def __init__(self): reload(sys) sys.setdefaultencoding('UTF-8') self.datatype = 'main' self.title = '网易云音乐' self.datalist = ['排行榜', '艺术家', '新碟上架', '精选歌单', '我的歌单', 'DJ节目', '打碟', '收藏', '搜索', '帮助'] self.offset = 0 self.index = 0 self.presentsongs = [] self.player = Player() self.ui = Ui() self.netease = NetEase() self.screen = curses.initscr() self.screen.keypad(1) self.step = 10 self.stack = [] self.djstack = [] self.userid = None self.username = None self.play_show_flag=False #定时器用,跳到播放歌曲 self.interrupt_handler=None self.delay=10 self.play_p=False #歌曲播放标记 self.kill_p=0 #kill线程标记 self.run_p=False #定时运行标记 self.index_c=False #定时完成标志 self.key=[None,None] #存储按键值及按键时的时间 self.next=False #下一曲切换标记 self.play_time_str='0' self.play_time_str_p=True #获取播放时间进程标记 self.play_length_str='0' #歌曲总长度 self.idx_idx=-1 #get_play_*函数用,保存上一个歌曲序列 self.mplayer_start_finished=False #mplayer获取歌曲完成标志 self.bar_p=False try: sfile = file(Constant.conf_dir + "/flavor.json",'r') data = json.loads(sfile.read()) self.collection = data['collection'] self.account = data['account'] sfile.close() except: self.collection = [] self.account = {}
class Menu: def __init__(self): reload(sys) sys.setdefaultencoding('UTF-8') self.datatype = 'main' self.title = '网易云音乐' self.datalist = ['排行榜', '艺术家', '新碟上架', '精选歌单', '我的歌单', 'DJ节目', '打碟', '收藏', '搜索', '帮助'] self.offset = 0 self.index = 0 self.storage = Storage() self.storage.load() self.collection = self.storage.database['collections'][0] self.player = Player() self.cache = Cache() self.ui = Ui() self.netease = NetEase() self.screen = curses.initscr() self.screen.keypad(1) self.step = 10 self.stack = [] self.djstack = [] self.userid = None self.username = None self.resume_play = True signal.signal(signal.SIGWINCH, self.change_term) signal.signal(signal.SIGINT, self.send_kill) self.START = time.time() def change_term(self, signum, frame): self.ui.screen.clear() self.ui.screen.refresh() def send_kill(self, signum, fram): self.player.stop() self.cache.quit() self.storage.save() curses.endwin() sys.exit() def start(self): self.START = time.time() // 1 self.ui.build_menu(self.datatype, self.title, self.datalist, self.offset, self.index, self.step, self.START) self.ui.build_process_bar(self.player.process_location, self.player.process_length, self.player.playing_flag, self.player.pause_flag, self.storage.database['player_info']['playing_mode']) self.stack.append([self.datatype, self.title, self.datalist, self.offset, self.index]) while True: datatype = self.datatype title = self.title datalist = self.datalist offset = self.offset idx = index = self.index step = self.step stack = self.stack djstack = self.djstack self.screen.timeout(500) key = self.screen.getch() self.ui.screen.refresh() # term resize if key == -1: self.ui.update_size() self.player.update_size() # 退出 if key == ord('q'): break # 退出并清除用户信息 if key == ord('w'): self.storage.database['user'] = { "username": "", "password": "", } break # 上移 elif key == ord('k'): self.index = carousel(offset, min(len(datalist), offset + step) - 1, idx - 1) self.START = time.time() # 下移 elif key == ord('j'): self.index = carousel(offset, min(len(datalist), offset + step) - 1, idx + 1) self.START = time.time() # 数字快捷键 elif ord('0') <= key <= ord('9'): if self.datatype == 'songs' or self.datatype == 'djchannels' or self.datatype == 'help': continue idx = key - ord('0') self.ui.build_menu(self.datatype, self.title, self.datalist, self.offset, idx, self.step, self.START) self.ui.build_loading() self.dispatch_enter(idx) self.index = 0 self.offset = 0 # 向上翻页 elif key == ord('u'): if offset == 0: continue self.START = time.time() self.offset -= step # e.g. 23 - 10 = 13 --> 10 self.index = (index - step) // step * step # 向下翻页 elif key == ord('d'): if offset + step >= len(datalist): continue self.START = time.time() self.offset += step # e.g. 23 + 10 = 33 --> 30 self.index = (index + step) // step * step # 前进 elif key == ord('l') or key == 10: if self.datatype == 'songs' or self.datatype == 'djchannels' or self.datatype == 'help': continue self.START = time.time() self.ui.build_loading() self.dispatch_enter(idx) self.index = 0 self.offset = 0 # 回退 elif key == ord('h'): # if not main menu if len(self.stack) == 1: continue self.START = time.time() up = stack.pop() self.datatype = up[0] self.title = up[1] self.datalist = up[2] self.offset = up[3] self.index = up[4] # 搜索 elif key == ord('f'): # 8 is the 'search' menu self.dispatch_enter(8) # 播放下一曲 elif key == ord(']'): if len(self.storage.database["player_info"]["player_list"]) == 0: continue self.player.next() time.sleep(0.1) # 播放上一曲 elif key == ord('['): if len(self.storage.database["player_info"]["player_list"]) == 0: continue self.player.prev() time.sleep(0.1) # 增加音量 elif key == ord('='): self.player.volume_up() # 减少音量 elif key == ord('-'): self.player.volume_down() # 随机播放 elif key == ord('?'): if len(self.storage.database["player_info"]["player_list"]) == 0: continue self.player.shuffle() time.sleep(0.1) # 播放、暂停 elif key == ord(' '): try: if self.datalist[idx] == self.storage.database["songs"][str(self.player.playing_id)]: self.player.play_and_pause(self.storage.database['player_info']['idx']) time.sleep(0.1) continue except: pass if datatype == 'songs': self.resume_play = False self.player.new_player_list('songs', self.title, self.datalist, -1) self.player.play_and_pause(idx) elif datatype == 'djchannels': self.resume_play = False self.player.new_player_list('djchannels', self.title, self.datalist, -1) self.player.play_and_pause(idx) else: self.player.play_and_pause(self.storage.database['player_info']['idx']) time.sleep(0.1) # 加载当前播放列表 elif key == ord('p'): if len(self.storage.database['player_info']['player_list']) == 0: continue self.stack.append([self.datatype, self.title, self.datalist, self.offset, self.index]) self.datatype = self.storage.database['player_info']['player_list_type'] self.title = self.storage.database['player_info']['player_list_title'] self.datalist = [] for i in self.storage.database['player_info']['player_list']: self.datalist.append(self.storage.database['songs'][i]) self.index = self.storage.database['player_info']['idx'] self.offset = self.storage.database['player_info']['idx'] / self.step * self.step if self.resume_play: self.storage.database['player_info']['idx'] = -1 self.player.play_and_pause(self.index) self.resume_play = False # 播放模式切换 elif key == ord('P'): self.storage.database['player_info']['playing_mode'] = \ (self.storage.database['player_info']['playing_mode'] + 1) % 5 # 添加到打碟歌单 elif key == ord('a'): if datatype == 'songs' and len(datalist) != 0: self.djstack.append(datalist[idx]) elif datatype == 'artists': pass # 加载打碟歌单 elif key == ord('z'): self.stack.append([datatype, title, datalist, offset, index]) self.datatype = 'songs' self.title = '网易云音乐 > 打碟' self.datalist = self.djstack self.offset = 0 self.index = 0 # 添加到收藏歌曲 elif key == ord('s'): if (datatype == 'songs' or datatype == 'djchannels') and len(datalist) != 0: self.collection.append(datalist[idx]) # 加载收藏歌曲 elif key == ord('c'): self.stack.append([datatype, title, datalist, offset, index]) self.datatype = 'songs' self.title = '网易云音乐 > 收藏' self.datalist = self.collection self.offset = 0 self.index = 0 # 从当前列表移除 elif key == ord('r'): if datatype != 'main' and len(datalist) != 0: self.datalist.pop(idx) self.index = carousel(offset, min(len(datalist), offset + step) - 1, idx) # 当前项目下移 elif key == ord("J"): if datatype != 'main' and len(datalist) != 0 and idx + 1 != len(self.datalist): self.START = time.time() song = self.datalist.pop(idx) self.datalist.insert(idx + 1, song) self.index = idx + 1 # 翻页 if self.index >= offset + step: self.offset = offset + step # 当前项目上移 elif key == ord("K"): if datatype != 'main' and len(datalist) != 0 and idx != 0: self.START = time.time() song = self.datalist.pop(idx) self.datalist.insert(idx - 1, song) self.index = idx - 1 # 翻页 if self.index < offset: self.offset = offset - step elif key == ord('m'): if datatype != 'main': self.stack.append([datatype, title, datalist, offset, index]) self.datatype = self.stack[0][0] self.title = self.stack[0][1] self.datalist = self.stack[0][2] self.offset = 0 self.index = 0 elif key == ord('g'): if datatype == 'help': webbrowser.open_new_tab('https://github.com/darknessomi/musicbox') self.ui.build_process_bar(self.player.process_location, self.player.process_length, self.player.playing_flag, self.player.pause_flag, self.storage.database['player_info']['playing_mode']) self.ui.build_menu(self.datatype, self.title, self.datalist, self.offset, self.index, self.step, self.START) self.player.stop() self.cache.quit() self.storage.save() curses.endwin() def dispatch_enter(self, idx): # The end of stack netease = self.netease datatype = self.datatype title = self.title datalist = self.datalist offset = self.offset index = self.index self.stack.append([datatype, title, datalist, offset, index]) if datatype == 'main': self.choice_channel(idx) # 该艺术家的热门歌曲 elif datatype == 'artists': artist_id = datalist[idx]['artist_id'] songs = netease.artists(artist_id) self.datatype = 'songs' self.datalist = netease.dig_info(songs, 'songs') self.title += ' > ' + datalist[idx]['artists_name'] # 该专辑包含的歌曲 elif datatype == 'albums': album_id = datalist[idx]['album_id'] songs = netease.album(album_id) self.datatype = 'songs' self.datalist = netease.dig_info(songs, 'songs') self.title += ' > ' + datalist[idx]['albums_name'] # 精选歌单选项 elif datatype == 'playlists': data = self.datalist[idx] self.datatype = data['datatype'] self.datalist = netease.dig_info(data['callback'](), self.datatype) self.title += ' > ' + data['title'] # 全站置顶歌单包含的歌曲 elif datatype == 'top_playlists': log.debug(datalist) playlist_id = datalist[idx]['playlist_id'] songs = netease.playlist_detail(playlist_id) self.datatype = 'songs' self.datalist = netease.dig_info(songs, 'songs') self.title += ' > ' + datalist[idx]['playlists_name'] # 分类精选 elif datatype == 'playlist_classes': # 分类名称 data = self.datalist[idx] self.datatype = 'playlist_class_detail' self.datalist = netease.dig_info(data, self.datatype) self.title += ' > ' + data log.debug(self.datalist) # 某一分类的详情 elif datatype == 'playlist_class_detail': # 子类别 data = self.datalist[idx] self.datatype = 'top_playlists' self.datalist = netease.dig_info(netease.top_playlists(data), self.datatype) log.debug(self.datalist) self.title += ' > ' + data # 歌曲榜单 elif datatype == 'toplists': songs = netease.top_songlist(idx) self.title += ' > ' + self.datalist[idx] self.datalist = netease.dig_info(songs, 'songs') self.datatype = 'songs' # 搜索菜单 elif datatype == 'search': ui = self.ui # no need to do stack.append, Otherwise there will be a bug when you input key 'h' to return # if idx in range(1, 5): # self.stack.append([self.datatype, self.title, self.datalist, self.offset, self.index]) self.index = 0 self.offset = 0 if idx == 0: # 搜索结果可以用top_playlists处理 self.datatype = 'top_playlists' self.datalist = ui.build_search('search_playlist') self.title = '精选歌单搜索列表' elif idx == 1: self.datatype = 'songs' self.datalist = ui.build_search('songs') self.title = '歌曲搜索列表' elif idx == 2: self.datatype = 'artists' self.datalist = ui.build_search('artists') self.title = '艺术家搜索列表' elif idx == 3: self.datatype = 'albums' self.datalist = ui.build_search('albums') self.title = '专辑搜索列表' def choice_channel(self, idx): # 排行榜 netease = self.netease if idx == 0: self.datalist = netease.return_toplists() self.title += ' > 排行榜' self.datatype = 'toplists' # 艺术家 elif idx == 1: artists = netease.top_artists() self.datalist = netease.dig_info(artists, 'artists') self.title += ' > 艺术家' self.datatype = 'artists' # 新碟上架 elif idx == 2: albums = netease.new_albums() self.datalist = netease.dig_info(albums, 'albums') self.title += ' > 新碟上架' self.datatype = 'albums' # 精选歌单 elif idx == 3: self.datalist = [ { 'title': '全站置顶', 'datatype': 'top_playlists', 'callback': netease.top_playlists }, { 'title': '分类精选', 'datatype': 'playlist_classes', 'callback': netease.playlist_classes } ] self.title += ' > 精选歌单' self.datatype = 'playlists' # 我的歌单 elif idx == 4: # 未登录 if self.userid is None: # 使用本地存储了账户登录 if self.storage.database['user']['username'] != "": user_info = netease.login(self.storage.database['user']['username'], self.storage.database['user']['password']) # 本地没有存储账户,或本地账户失效,则引导录入 if self.storage.database['user']['username'] == "" or user_info['code'] != 200: data = self.ui.build_login() # 取消登录 if data == -1: return user_info = data[0] self.storage.database['user']['username'] = data[1][0] self.storage.database['user']['password'] = data[1][1] self.username = user_info['profile']['nickname'] self.userid = user_info['account']['id'] # 读取登录之后的用户歌单 myplaylist = netease.user_playlist(self.userid) self.datatype = 'top_playlists' self.datalist = netease.dig_info(myplaylist, self.datatype) self.title += ' > ' + self.username + ' 的歌单' # DJ节目 elif idx == 5: self.datatype = 'djchannels' self.title += ' > DJ节目' self.datalist = netease.djchannels() # 打碟 elif idx == 6: self.datatype = 'songs' self.title += ' > 打碟' self.datalist = self.djstack # 收藏 elif idx == 7: self.datatype = 'songs' self.title += ' > 收藏' self.datalist = self.collection # 搜索 elif idx == 8: self.datatype = 'search' self.title += ' > 搜索' self.datalist = ['歌曲', '艺术家', '专辑', '网易精选集'] # 帮助 elif idx == 9: self.datatype = 'help' self.title += ' > 帮助' self.datalist = shortcut self.offset = 0 self.index = 0
class Menu: def __init__(self): reload(sys) sys.setdefaultencoding("UTF-8") self.datatype = "main" self.title = "网易云音乐" self.datalist = ["排行榜", "艺术家", "新碟上架", "精选歌单", "我的歌单", "DJ节目", "打碟", "收藏", "搜索", "帮助"] self.offset = 0 self.index = 0 self.storage = Storage() self.storage.load() self.collection = self.storage.database["collections"][0] self.player = Player() self.ui = Ui() self.netease = NetEase() self.screen = curses.initscr() self.screen.keypad(1) self.step = 10 self.stack = [] self.djstack = [] self.userid = None self.username = None self.resume_play = True signal.signal(signal.SIGWINCH, self.change_term) signal.signal(signal.SIGINT, self.send_kill) self.START = time.time() def change_term(self, signum, frame): self.ui.screen.clear() self.ui.screen.refresh() def send_kill(self, signum, fram): self.player.stop() self.storage.save() curses.endwin() sys.exit() def start(self): self.START = time.time() // 1 self.ui.build_menu(self.datatype, self.title, self.datalist, self.offset, self.index, self.step, self.START) self.ui.build_process_bar( self.player.process_location, self.player.process_length, self.player.playing_flag, self.player.pause_flag, self.storage.database["player_info"]["playing_mode"], ) self.stack.append([self.datatype, self.title, self.datalist, self.offset, self.index]) while True: datatype = self.datatype title = self.title datalist = self.datalist offset = self.offset idx = index = self.index step = self.step stack = self.stack djstack = self.djstack self.screen.timeout(500) key = self.screen.getch() self.ui.screen.refresh() # term resize if key == -1: self.ui.update_size() self.player.update_size() # 退出 if key == ord("q"): break # 退出并清除用户信息 if key == ord("w"): self.storage.database["user"] = {"username": "", "password": ""} break # 上移 elif key == ord("k"): self.index = carousel(offset, min(len(datalist), offset + step) - 1, idx - 1) self.START = time.time() # 下移 elif key == ord("j"): self.index = carousel(offset, min(len(datalist), offset + step) - 1, idx + 1) self.START = time.time() # 数字快捷键 elif ord("0") <= key <= ord("9"): if self.datatype == "songs" or self.datatype == "djchannels" or self.datatype == "help": continue idx = key - ord("0") self.ui.build_menu(self.datatype, self.title, self.datalist, self.offset, idx, self.step, self.START) self.ui.build_loading() self.dispatch_enter(idx) self.index = 0 self.offset = 0 # 向上翻页 elif key == ord("u"): if offset == 0: continue self.START = time.time() self.offset -= step # e.g. 23 - 10 = 13 --> 10 self.index = (index - step) // step * step # 向下翻页 elif key == ord("d"): if offset + step >= len(datalist): continue self.START = time.time() self.offset += step # e.g. 23 + 10 = 33 --> 30 self.index = (index + step) // step * step # 前进 elif key == ord("l") or key == 10: if self.datatype == "songs" or self.datatype == "djchannels" or self.datatype == "help": continue self.START = time.time() self.ui.build_loading() self.dispatch_enter(idx) self.index = 0 self.offset = 0 # 回退 elif key == ord("h"): # if not main menu if len(self.stack) == 1: continue self.START = time.time() up = stack.pop() self.datatype = up[0] self.title = up[1] self.datalist = up[2] self.offset = up[3] self.index = up[4] # 搜索 elif key == ord("f"): # 8 is the 'search' menu self.dispatch_enter(8) # 播放下一曲 elif key == ord("]"): if len(self.storage.database["player_info"]["player_list"]) == 0: continue self.player.next() time.sleep(0.1) # 播放上一曲 elif key == ord("["): if len(self.storage.database["player_info"]["player_list"]) == 0: continue self.player.prev() time.sleep(0.1) # 增加音量 elif key == ord("="): self.player.volume_up() # 减少音量 elif key == ord("-"): self.player.volume_down() # 随机播放 elif key == ord("?"): if len(self.storage.database["player_info"]["player_list"]) == 0: continue self.player.shuffle() time.sleep(0.1) # 播放、暂停 elif key == ord(" "): try: if self.datalist[idx] == self.storage.database["songs"][str(self.player.playing_id)]: self.player.play_and_pause(self.storage.database["player_info"]["idx"]) time.sleep(0.1) continue except: pass if datatype == "songs": self.resume_play = False self.player.new_player_list("songs", self.title, self.datalist, -1) self.player.play_and_pause(idx) elif datatype == "djchannels": self.resume_play = False self.player.new_player_list("djchannels", self.title, self.datalist, -1) self.player.play_and_pause(idx) else: self.player.play_and_pause(self.storage.database["player_info"]["idx"]) time.sleep(0.1) # 加载当前播放列表 elif key == ord("p"): if len(self.storage.database["player_info"]["player_list"]) == 0: continue self.stack.append([self.datatype, self.title, self.datalist, self.offset, self.index]) self.datatype = self.storage.database["player_info"]["player_list_type"] self.title = self.storage.database["player_info"]["player_list_title"] self.datalist = [] for i in self.storage.database["player_info"]["player_list"]: self.datalist.append(self.storage.database["songs"][i]) self.index = self.storage.database["player_info"]["idx"] self.offset = self.storage.database["player_info"]["idx"] / self.step * self.step if self.resume_play: self.storage.database["player_info"]["idx"] = -1 self.player.play_and_pause(self.index) self.resume_play = False # 播放模式切换 elif key == ord("P"): self.storage.database["player_info"]["playing_mode"] = ( self.storage.database["player_info"]["playing_mode"] + 1 ) % 5 # 添加到打碟歌单 elif key == ord("a"): if datatype == "songs" and len(datalist) != 0: self.djstack.append(datalist[idx]) elif datatype == "artists": pass # 加载打碟歌单 elif key == ord("z"): self.stack.append([datatype, title, datalist, offset, index]) self.datatype = "songs" self.title = "网易云音乐 > 打碟" self.datalist = self.djstack self.offset = 0 self.index = 0 # 添加到收藏歌曲 elif key == ord("s"): if (datatype == "songs" or datatype == "djchannels") and len(datalist) != 0: self.collection.append(datalist[idx]) # 加载收藏歌曲 elif key == ord("c"): self.stack.append([datatype, title, datalist, offset, index]) self.datatype = "songs" self.title = "网易云音乐 > 收藏" self.datalist = self.collection self.offset = 0 self.index = 0 # 从当前列表移除 elif key == ord("r"): if datatype != "main" and len(datalist) != 0: self.datalist.pop(idx) self.index = carousel(offset, min(len(datalist), offset + step) - 1, idx) # 当前项目下移 elif key == ord("J"): if datatype != "main" and len(datalist) != 0 and idx + 1 != len(self.datalist): self.START = time.time() song = self.datalist.pop(idx) self.datalist.insert(idx + 1, song) self.index = idx + 1 # 翻页 if self.index >= offset + step: self.offset = offset + step # 当前项目上移 elif key == ord("K"): if datatype != "main" and len(datalist) != 0 and idx != 0: self.START = time.time() song = self.datalist.pop(idx) self.datalist.insert(idx - 1, song) self.index = idx - 1 # 翻页 if self.index < offset: self.offset = offset - step elif key == ord("m"): if datatype != "main": self.stack.append([datatype, title, datalist, offset, index]) self.datatype = self.stack[0][0] self.title = self.stack[0][1] self.datalist = self.stack[0][2] self.offset = 0 self.index = 0 elif key == ord("g"): if datatype == "help": webbrowser.open_new_tab("https://github.com/darknessomi/musicbox") self.ui.build_process_bar( self.player.process_location, self.player.process_length, self.player.playing_flag, self.player.pause_flag, self.storage.database["player_info"]["playing_mode"], ) self.ui.build_menu(self.datatype, self.title, self.datalist, self.offset, self.index, self.step, self.START) self.player.stop() self.storage.save() curses.endwin() def dispatch_enter(self, idx): # The end of stack netease = self.netease datatype = self.datatype title = self.title datalist = self.datalist offset = self.offset index = self.index self.stack.append([datatype, title, datalist, offset, index]) if datatype == "main": self.choice_channel(idx) # 该艺术家的热门歌曲 elif datatype == "artists": artist_id = datalist[idx]["artist_id"] songs = netease.artists(artist_id) self.datatype = "songs" self.datalist = netease.dig_info(songs, "songs") self.title += " > " + datalist[idx]["artists_name"] # 该专辑包含的歌曲 elif datatype == "albums": album_id = datalist[idx]["album_id"] songs = netease.album(album_id) self.datatype = "songs" self.datalist = netease.dig_info(songs, "songs") self.title += " > " + datalist[idx]["albums_name"] # 精选歌单选项 elif datatype == "playlists": data = self.datalist[idx] self.datatype = data["datatype"] self.datalist = netease.dig_info(data["callback"](), self.datatype) self.title += " > " + data["title"] # 全站置顶歌单包含的歌曲 elif datatype == "top_playlists": log.debug(datalist) playlist_id = datalist[idx]["playlist_id"] songs = netease.playlist_detail(playlist_id) self.datatype = "songs" self.datalist = netease.dig_info(songs, "songs") self.title += " > " + datalist[idx]["playlists_name"] # 分类精选 elif datatype == "playlist_classes": # 分类名称 data = self.datalist[idx] self.datatype = "playlist_class_detail" self.datalist = netease.dig_info(data, self.datatype) self.title += " > " + data log.debug(self.datalist) # 某一分类的详情 elif datatype == "playlist_class_detail": # 子类别 data = self.datalist[idx] self.datatype = "top_playlists" self.datalist = netease.dig_info(netease.top_playlists(data), self.datatype) log.debug(self.datalist) self.title += " > " + data # 歌曲榜单 elif datatype == "toplists": songs = netease.top_songlist(idx) self.title += " > " + self.datalist[idx] self.datalist = netease.dig_info(songs, "songs") self.datatype = "songs" # 搜索菜单 elif datatype == "search": ui = self.ui # no need to do stack.append, Otherwise there will be a bug when you input key 'h' to return # if idx in range(1, 5): # self.stack.append([self.datatype, self.title, self.datalist, self.offset, self.index]) self.index = 0 self.offset = 0 if idx == 0: # 搜索结果可以用top_playlists处理 self.datatype = "top_playlists" self.datalist = ui.build_search("search_playlist") self.title = "精选歌单搜索列表" elif idx == 1: self.datatype = "songs" self.datalist = ui.build_search("songs") self.title = "歌曲搜索列表" elif idx == 2: self.datatype = "artists" self.datalist = ui.build_search("artists") self.title = "艺术家搜索列表" elif idx == 3: self.datatype = "albums" self.datalist = ui.build_search("albums") self.title = "专辑搜索列表" def choice_channel(self, idx): # 排行榜 netease = self.netease if idx == 0: self.datalist = netease.return_toplists() self.title += " > 排行榜" self.datatype = "toplists" # 艺术家 elif idx == 1: artists = netease.top_artists() self.datalist = netease.dig_info(artists, "artists") self.title += " > 艺术家" self.datatype = "artists" # 新碟上架 elif idx == 2: albums = netease.new_albums() self.datalist = netease.dig_info(albums, "albums") self.title += " > 新碟上架" self.datatype = "albums" # 精选歌单 elif idx == 3: self.datalist = [ {"title": "全站置顶", "datatype": "top_playlists", "callback": netease.top_playlists}, {"title": "分类精选", "datatype": "playlist_classes", "callback": netease.playlist_classes}, ] self.title += " > 精选歌单" self.datatype = "playlists" # 我的歌单 elif idx == 4: # 未登录 if self.userid is None: # 使用本地存储了账户登录 if self.storage.database["user"]["username"] != "": user_info = netease.login( self.storage.database["user"]["username"], self.storage.database["user"]["password"] ) # 本地没有存储账户,或本地账户失效,则引导录入 if self.storage.database["user"]["username"] == "" or user_info["code"] != 200: data = self.ui.build_login() # 取消登录 if data == -1: return user_info = data[0] self.storage.database["user"]["username"] = data[1][0] self.storage.database["user"]["password"] = data[1][1] self.username = user_info["profile"]["nickname"] self.userid = user_info["account"]["id"] # 读取登录之后的用户歌单 myplaylist = netease.user_playlist(self.userid) self.datatype = "top_playlists" self.datalist = netease.dig_info(myplaylist, self.datatype) self.title += " > " + self.username + " 的歌单" # DJ节目 elif idx == 5: self.datatype = "djchannels" self.title += " > DJ节目" self.datalist = netease.djchannels() # 打碟 elif idx == 6: self.datatype = "songs" self.title += " > 打碟" self.datalist = self.djstack # 收藏 elif idx == 7: self.datatype = "songs" self.title += " > 收藏" self.datalist = self.collection # 搜索 elif idx == 8: self.datatype = "search" self.title += " > 搜索" self.datalist = ["歌曲", "艺术家", "专辑", "网易精选集"] # 帮助 elif idx == 9: self.datatype = "help" self.title += " > 帮助" self.datalist = shortcut self.offset = 0 self.index = 0
class Player: def __init__(self): self.config = Config() self.ui = Ui() self.popen_handler = None # flag stop, prevent thread start self.playing_flag = False self.pause_flag = False self.process_length = 0 self.process_location = 0 self.process_first = False self.storage = Storage() self.info = self.storage.database["player_info"] self.songs = self.storage.database["songs"] self.playing_id = -1 self.cache = Cache() self.mpg123_parameters = self.config.get_item("mpg123_parameters") self.end_callback = None def popen_recall(self, onExit, popenArgs): """ Runs the given args in a subprocess.Popen, and then calls the function onExit when the subprocess completes. onExit is a callable object, and popenArgs is a lists/tuple of args that would give to subprocess.Popen. """ def runInThread(onExit, popenArgs): para = ['mpg123', '-R'] para[1:1] = self.mpg123_parameters self.popen_handler = subprocess.Popen(para, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE) self.popen_handler.stdin.write("V " + str(self.info["playing_volume"]) + "\n") self.popen_handler.stdin.write("L " + popenArgs + "\n") self.process_first = True while (True): if self.playing_flag == False: break try: strout = self.popen_handler.stdout.readline() except IOError: break if re.match("^\@F.*$", strout): process_data = strout.split(" ") process_location = float(process_data[4]) if self.process_first: self.process_length = process_location self.process_first = False self.process_location = 0 else: self.process_location = self.process_length - process_location continue if strout == "@P 0\n": self.popen_handler.stdin.write("Q\n") self.popen_handler.kill() break if self.playing_flag: self.next_idx() onExit() return def getLyric(): if 'lyric' not in self.songs[str(self.playing_id)].keys(): self.songs[str(self.playing_id)]["lyric"] = [] if len(self.songs[str(self.playing_id)]["lyric"]) > 0: return netease = NetEase() lyric = netease.song_lyric(self.playing_id) if (not lyric == []) or lyric == '未找到歌词': lyric = lyric.split('\n') self.songs[str(self.playing_id)]["lyric"] = lyric return def cacheSong(song_id, song_name, artist, song_url): def cacheExit(song_id, path): self.songs[str(song_id)]['cache'] = path self.cache.add(song_id, song_name, artist, song_url, cacheExit) self.cache.start_download() if 'cache' in popenArgs.keys() and os.path.isfile(popenArgs['cache']): thread = threading.Thread(target=runInThread, args=(onExit, popenArgs['cache'])) else: thread = threading.Thread(target=runInThread, args=(onExit, popenArgs['mp3_url'])) cache_thread = threading.Thread(target=cacheSong, args=( popenArgs['song_id'], popenArgs['song_name'], popenArgs['artist'], popenArgs['mp3_url'])) cache_thread.start() thread.start() lyric_download_thread = threading.Thread(target=getLyric, args=()) lyric_download_thread.start() # returns immediately after the thread starts return thread def get_playing_id(self): return self.playing_id def recall(self): if self.info["idx"] >= len(self.info["player_list"]) and self.end_callback != None: self.end_callback() if self.info["idx"] < 0 or self.info["idx"] >= len(self.info["player_list"]): self.info["idx"] = 0 self.stop() return self.playing_flag = True self.pause_flag = False item = self.songs[self.info["player_list"][self.info["idx"]]] self.ui.build_playinfo(item['song_name'], item['artist'], item['album_name'], item['quality'], time.time()) self.playing_id = item['song_id'] self.popen_recall(self.recall, item) def generate_shuffle_playing_list(self): del self.info["playing_list"][:] for i in range(0, len(self.info["player_list"])): self.info["playing_list"].append(i) random.shuffle(self.info["playing_list"]) self.info["ridx"] = 0 def new_player_list(self, type, title, datalist, offset): self.info["player_list_type"] = type self.info["player_list_title"] = title self.info["idx"] = offset del self.info["player_list"][:] del self.info["playing_list"][:] self.info["ridx"] = 0 for song in datalist: self.info["player_list"].append(str(song["song_id"])) if str(song["song_id"]) not in self.songs.keys(): self.songs[str(song["song_id"])] = song else: database_song = self.songs[str(song["song_id"])] if (database_song["song_name"] != song["song_name"] or database_song["quality"] != song["quality"]): self.songs[str(song["song_id"])] = song def append_songs(self, datalist): for song in datalist: self.info["player_list"].append(str(song["song_id"])) if str(song["song_id"]) not in self.songs.keys(): self.songs[str(song["song_id"])] = song else: database_song = self.songs[str(song["song_id"])] if (database_song["song_name"] != song["song_name"] or database_song["quality"] != song["quality"]): self.songs[str(song["song_id"])] = song if len(datalist) > 0 and self.info["playing_mode"] == 3 or self.info["playing_mode"] == 4: self.generate_shuffle_playing_list() def play_and_pause(self, idx): # if same playlists && idx --> same song :: pause/resume it if self.info["idx"] == idx: if self.pause_flag: self.resume() else: self.pause() else: self.info["idx"] = idx # if it's playing if self.playing_flag: self.switch() # start new play else: self.recall() # play another def switch(self): self.stop() # wait process be killed time.sleep(0.1) self.recall() def stop(self): if self.playing_flag and self.popen_handler: self.playing_flag = False try: self.popen_handler.stdin.write("Q\n") except: pass try: self.popen_handler.kill() except: return def pause(self): if not self.playing_flag and not self.popen_handler: return self.pause_flag = True os.kill(self.popen_handler.pid, signal.SIGSTOP) item = self.songs[self.info["player_list"][self.info["idx"]]] self.ui.build_playinfo(item['song_name'], item['artist'], item['album_name'], item['quality'], time.time(), pause=True) def resume(self): self.pause_flag = False os.kill(self.popen_handler.pid, signal.SIGCONT) item = self.songs[self.info["player_list"][self.info["idx"]]] self.ui.build_playinfo(item['song_name'], item['artist'], item['album_name'], item['quality'], time.time()) self.playing_id = item['song_id'] def next_idx(self): if self.info["idx"] < 0 or self.info["idx"] >= len(self.info["player_list"]): self.stop() return # Playing mode. 0 is ordered. 1 is orderde loop. 2 is single song loop. 3 is single random. 4 is random loop if self.info["playing_mode"] == 0: self.info["idx"] += 1 elif self.info["playing_mode"] == 1: self.info["idx"] = (self.info["idx"] + 1) % len(self.info["player_list"]) elif self.info["playing_mode"] == 2: self.info["idx"] = self.info["idx"] elif self.info["playing_mode"] == 3: if self.info["ridx"] >= len(self.info["playing_list"]): self.generate_shuffle_playing_list() try: now_songs = self.info["playing_list"].index(self.info["idx"]) temp = self.info["playing_list"][0] self.info["playing_list"][0] = self.info["playing_list"][now_songs] self.info["playing_list"][now_songs] = temp except: self.generate_shuffle_playing_list() elif self.info["playing_list"][self.info["ridx"]] != self.info["idx"]: self.generate_shuffle_playing_list() try: now_songs = self.info["playing_list"].index(self.info["idx"]) temp = self.info["playing_list"][0] self.info["playing_list"][0] = self.info["playing_list"][now_songs] self.info["playing_list"][now_songs] = temp except: self.generate_shuffle_playing_list() self.info["ridx"] += 1 if self.info["ridx"] >= len(self.info["playing_list"]): self.info["idx"] = len(self.info["playing_list"]) else: self.info["idx"] = self.info["playing_list"][self.info["ridx"]] elif self.info["playing_mode"] == 4: if self.info["ridx"] >= len(self.info["playing_list"]): self.generate_shuffle_playing_list() try: now_songs = self.info["playing_list"].index(self.info["idx"]) temp = self.info["playing_list"][0] self.info["playing_list"][0] = self.info["playing_list"][now_songs] self.info["playing_list"][now_songs] = temp except: self.generate_shuffle_playing_list() elif self.info["playing_list"][self.info["ridx"]] != self.info["idx"]: self.generate_shuffle_playing_list() try: now_songs = self.info["playing_list"].index(self.info["idx"]) temp = self.info["playing_list"][0] self.info["playing_list"][0] = self.info["playing_list"][now_songs] self.info["playing_list"][now_songs] = temp except: self.generate_shuffle_playing_list() self.info["ridx"] = (self.info["ridx"] + 1) % len(self.info["player_list"]) self.info["idx"] = self.info["playing_list"][self.info["ridx"]] else: self.info["idx"] += 1 def next(self): self.stop() time.sleep(0.01) self.next_idx() self.recall() def prev_idx(self): if self.info["idx"] < 0 or self.info["idx"] >= len(self.info["player_list"]): self.stop() return # Playing mode. 0 is ordered. 1 is orderde loop. 2 is single song loop. 3 is single random. 4 is random loop if self.info["playing_mode"] == 0: self.info["idx"] -= 1 elif self.info["playing_mode"] == 1: self.info["idx"] = (self.info["idx"] - 1) % len(self.info["player_list"]) elif self.info["playing_mode"] == 2: self.info["idx"] = self.info["idx"] elif self.info["playing_mode"] == 3: if self.info["ridx"] >= len(self.info["playing_list"]): self.generate_shuffle_playing_list() elif self.info["playing_list"][self.info["ridx"]] != self.info["idx"]: self.generate_shuffle_playing_list() self.info["ridx"] -= 1 if self.info["ridx"] < 0: self.info["ridx"] = 0 return self.info["idx"] = self.info["playing_list"][self.info["ridx"]] elif self.info["playing_mode"] == 4: if self.info["ridx"] >= len(self.info["playing_list"]): self.generate_shuffle_playing_list() elif self.info["playing_list"][self.info["ridx"]] != self.info["idx"]: self.generate_shuffle_playing_list() self.info["ridx"] = (self.info["ridx"] - 1) % len(self.info["player_list"]) self.info["idx"] = self.info["playing_list"][self.info["ridx"]] else: self.info["idx"] -= 1 def prev(self): self.stop() time.sleep(0.01) self.prev_idx() self.recall() def shuffle(self): self.stop() time.sleep(0.01) self.info["playing_mode"] = 3 self.generate_shuffle_playing_list() self.info["idx"] = self.info["playing_list"][self.info["ridx"]] self.recall() def volume_up(self): self.info["playing_volume"] = self.info["playing_volume"] + 7 if (self.info["playing_volume"] > 100): self.info["playing_volume"] = 100 if not self.playing_flag: return try: self.popen_handler.stdin.write("V " + str(self.info["playing_volume"]) + "\n") except: self.switch() def volume_down(self): self.info["playing_volume"] = self.info["playing_volume"] - 7 if (self.info["playing_volume"] < 0): self.info["playing_volume"] = 0 if not self.playing_flag: return try: self.popen_handler.stdin.write("V " + str(self.info["playing_volume"]) + "\n") except: self.switch() def update_size(self): try: self.ui.update_size() item = self.songs[self.info["player_list"][self.info["idx"]]] if self.playing_flag: self.ui.build_playinfo(item['song_name'], item['artist'], item['album_name'], item['quality'], time.time()) if self.pause_flag: self.ui.build_playinfo(item['song_name'], item['artist'], item['album_name'], item['quality'], time.time(), pause=True) except: pass
class Menu: def __init__(self): reload(sys) sys.setdefaultencoding('UTF-8') self.data_type = 'main' # Title of the application self.title = '网易云音乐' # Main-menu list self.data_list = ['排行榜', '艺术家', '新碟上架', '精选歌单', '我的歌单', 'DJ节目', '打碟', '收藏', '搜索', '帮助'] # Which page of the data_list is displayed (data_list may be displayed in multiple pages self.page_index = 0 # The index of the current selected line self.current_line_index = 0 self.present_songs = [] self.player = Player() self.ui = Ui() self.netease = NetEase() self.screen = curses.initscr() self.screen.keypad(1) self.page_size = 10 # The number of lines that can be displayed on one page. self.stack = [] self.dj_stack = [] self.user_id = None self.user_name = None # Read in the collection and account in flavor.json try: config_file = file(Constant.conf_dir + "/flavor.json", 'r') data = json.loads(config_file.read()) self.collection = data['collection'] self.account = data['account'] config_file.close() except: self.collection = [] self.account = {} def start(self): # draw the main menu self.ui.build_menu(self.data_type, self.title, self.data_list, self.page_index, self.current_line_index, self.page_size) # push current menu into stack self.stack.append([self.data_type, self.title, self.data_list, self.page_index, self.current_line_index]) # Main loop while True: # refresh the menu data_type = self.data_type title = self.title data_list = self.data_list page_index = self.page_index idx = current_line_index = self.current_line_index page_size = self.page_size stack = self.stack dj_stack = self.dj_stack self.ui.screen.refresh() # fetch a user's command key = self.screen.getch() # quit if key == ord('q'): break # move up elif key == ord('k') or key == curses.KEY_UP: self.current_line_index = carousel(page_index, min(len(data_list), page_index + page_size) - 1, idx - 1) # DEBUG # self.ui.screen.addstr(0, 0,'current_line_index: {}, begin: {}, end: {}'.format(self.current_line_index, page_index, min(len(data_list), page_index+page_size))) # move down elif key == ord('j') or key == curses.KEY_DOWN: self.current_line_index = carousel(page_index, min(len(data_list), page_index + page_size) - 1, idx + 1) # DEBUG # self.ui.screen.addstr(0, 0,'current_line_index: {}, begin: {}, end: {}'.format(self.current_line_index, page_index, min(len(data_list), page_index+page_size))) # number shortcut elif ord('0') <= key <= ord('9'): if self.data_type == 'songs' or self.data_type == 'djchannels' or self.data_type == 'help': continue idx = key - ord('0') self.ui.build_menu(self.data_type, self.title, self.data_list, self.page_index, idx, self.page_size) self.ui.build_loading() self.dispatch_enter(idx) self.current_line_index = 0 self.page_index = 0 # 向上翻页 elif key == ord('u') or key == curses.KEY_PPAGE: if page_index == 0: continue self.page_index -= page_size # Move to first line of the page self.current_line_index = (current_line_index - page_size) // page_size * page_size # 向下翻页 elif key == ord('d') or key == curses.KEY_NPAGE: if page_index + page_size >= len(data_list): continue self.page_index += page_size # Move to first line of the page self.current_line_index = (current_line_index + page_size) // page_size * page_size # 前进 elif key == ord('l') or key == 10 or key == curses.KEY_RIGHT: if self.data_type == 'songs' or self.data_type == 'djchannels' or self.data_type == 'help': continue self.ui.build_loading() self.dispatch_enter(idx) self.current_line_index = 0 self.page_index = 0 # 回退 elif key == ord('h') or key == curses.KEY_LEFT: # if not main menu if len(self.stack) == 1: continue last_menu = stack.pop() self.data_type = last_menu[0] self.title = last_menu[1] self.data_list = last_menu[2] self.page_index = last_menu[3] self.current_line_index = last_menu[4] # 搜索 elif key == ord('f'): self.search() # 播放下一曲 elif key == ord(']') or key == curses.KEY_NEXT: if len(self.present_songs) == 0: continue self.player.next() time.sleep(0.1) # 播放上一曲 elif key == ord('[') or key == curses.KEY_PREVIOUS: if len(self.present_songs) == 0: continue self.player.prev() time.sleep(0.1) # 播放、暂停 elif key == ord(' '): if data_type == 'songs': self.present_songs = ['songs', title, data_list, page_index, current_line_index] elif data_type == 'djchannels': self.present_songs = ['djchannels', title, data_list, page_index, current_line_index] self.player.play(data_type, data_list, idx) time.sleep(0.1) # 加载当前播放列表 elif key == ord('p'): if len(self.present_songs) == 0: continue self.stack.append([data_type, title, data_list, page_index, current_line_index]) self.data_type = self.present_songs[0] self.title = self.present_songs[1] self.data_list = self.present_songs[2] self.page_index = self.present_songs[3] self.current_line_index = self.present_songs[4] # 添加到打碟歌单 elif key == ord('a'): if data_type == 'songs' and len(data_list) != 0: self.dj_stack.append(data_list[idx]) elif data_type == 'artists': pass # 加载打碟歌单 elif key == ord('z'): self.stack.append([data_type, title, data_list, page_index, current_line_index]) self.data_type = 'songs' self.title = '网易云音乐 > 打碟' self.data_list = self.dj_stack self.page_index = 0 self.current_line_index = 0 # 添加到收藏歌曲 elif key == ord('s'): if (data_type == 'songs' or data_type == 'djchannels') and len(data_list) != 0: self.collection.append(data_list[idx]) # 加载收藏歌曲 elif key == ord('c'): self.stack.append([data_type, title, data_list, page_index, current_line_index]) self.data_type = 'songs' self.title = '网易云音乐 > 收藏' self.data_list = self.collection self.page_index = 0 self.current_line_index = 0 # 从当前列表移除 elif key == ord('r'): if data_type != 'main' and len(data_list) != 0: self.data_list.pop(idx) self.current_line_index = carousel(page_index, min(len(data_list), page_index + page_size) - 1, idx) elif key == ord('m'): if data_type != 'main': self.stack.append([data_type, title, data_list, page_index, current_line_index]) self.data_type = self.stack[0][0] self.title = self.stack[0][1] self.data_list = self.stack[0][2] self.page_index = 0 self.current_line_index = 0 elif key == ord('g'): if data_type == 'help': webbrowser.open_new_tab('https://github.com/darknessomi/musicbox') elif key == ord('\\'): self.player.next_play_mode() # refresh the window self.ui.build_menu(self.data_type, self.title, self.data_list, self.page_index, self.current_line_index, self.page_size) self.player.stop() sfile = file(Constant.conf_dir + "/flavor.json", 'w') data = { 'account': self.account, 'collection': self.collection } sfile.write(json.dumps(data)) sfile.close() curses.endwin() def dispatch_enter(self, idx): # The end of stack netease = self.netease datatype = self.data_type title = self.title datalist = self.data_list offset = self.page_index index = self.current_line_index self.stack.append([datatype, title, datalist, offset, index]) if datatype == 'main': self.choice_channel(idx) # 该艺术家的热门歌曲 elif datatype == 'artists': artist_id = datalist[idx]['artist_id'] songs = netease.artists(artist_id) self.data_type = 'songs' self.data_list = netease.dig_info(songs, 'songs') self.title += ' > ' + datalist[idx]['artists_name'] # 该专辑包含的歌曲 elif datatype == 'albums': album_id = datalist[idx]['album_id'] songs = netease.album(album_id) self.data_type = 'songs' self.data_list = netease.dig_info(songs, 'songs') self.title += ' > ' + datalist[idx]['albums_name'] # 精选歌单选项 elif datatype == 'playlists': data = self.data_list[idx] self.data_type = data['datatype'] self.data_list = netease.dig_info(data['callback'](), self.data_type) self.title += ' > ' + data['title'] # 全站置顶歌单包含的歌曲 elif datatype == 'top_playlists': log.debug(datalist) playlist_id = datalist[idx]['playlist_id'] songs = netease.playlist_detail(playlist_id) self.data_type = 'songs' self.data_list = netease.dig_info(songs, 'songs') self.title += ' > ' + datalist[idx]['playlists_name'] # 分类精选 elif datatype == 'playlist_classes': # 分类名称 data = self.data_list[idx] self.data_type = 'playlist_class_detail' self.data_list = netease.dig_info(data, self.data_type) self.title += ' > ' + data log.debug(self.data_list) # 某一分类的详情 elif datatype == 'playlist_class_detail': # 子类别 data = self.data_list[idx] self.data_type = 'top_playlists' self.data_list = netease.dig_info(netease.top_playlists(data), self.data_type) log.debug(self.data_list) self.title += ' > ' + data def choice_channel(self, idx): # 排行榜 netease = self.netease if idx == 0: songs = netease.top_songlist() self.data_list = netease.dig_info(songs, 'songs') self.title += ' > 排行榜' self.data_type = 'songs' # 艺术家 elif idx == 1: artists = netease.top_artists() self.data_list = netease.dig_info(artists, 'artists') self.title += ' > 艺术家' self.data_type = 'artists' # 新碟上架 elif idx == 2: albums = netease.new_albums() self.data_list = netease.dig_info(albums, 'albums') self.title += ' > 新碟上架' self.data_type = 'albums' # 精选歌单 elif idx == 3: self.data_list = [ { 'title': '全站置顶', 'datatype': 'top_playlists', 'callback': netease.top_playlists }, { 'title': '分类精选', 'datatype': 'playlist_classes', 'callback': netease.playlist_classes } ] self.title += ' > 精选歌单' self.data_type = 'playlists' # 我的歌单 elif idx == 4: # 未登录 if self.user_id is None: # 使用本地存储了账户登录 if self.account: user_info = netease.login(self.account[0], self.account[1]) else: user_info = {} # 本地没有存储账户,或本地账户失效,则引导录入 # if self.account == {} or user_info['code'] != 200: if self.account == {} or user_info['code'] != 200: data = self.ui.build_login() # 取消登录 if data == -1: return user_info = data[0] self.account = data[1] self.user_name = user_info['profile']['nickname'] self.user_id = user_info['account']['id'] # 读取登录之后的用户歌单 myplaylist = netease.user_playlist(self.user_id) self.data_type = 'top_playlists' self.data_list = netease.dig_info(myplaylist, self.data_type) self.title += ' > ' + self.user_name + ' 的歌单' # DJ节目 elif idx == 5: self.data_type = 'djchannels' self.title += ' > DJ节目' self.data_list = netease.djchannels() # 打碟 elif idx == 6: self.data_type = 'songs' self.title += ' > 打碟' self.data_list = self.dj_stack # 收藏 elif idx == 7: self.data_type = 'songs' self.title += ' > 收藏' self.data_list = self.collection # 搜索 elif idx == 8: self.search() # 帮助 elif idx == 9: self.data_type = 'help' self.title += ' > 帮助' self.data_list = shortcut self.page_index = 0 self.current_line_index = 0 def search(self): ui = self.ui x = ui.build_search_menu() # if do search, push current info into stack if x in range(ord('1'), ord('5')): self.stack.append([self.data_type, self.title, self.data_list, self.page_index, self.current_line_index]) self.current_line_index = 0 self.page_index = 0 if x == ord('1'): self.data_type = 'songs' self.data_list = ui.build_search('songs') self.title = '歌曲搜索列表' elif x == ord('2'): self.data_type = 'artists' self.data_list = ui.build_search('artists') self.title = '艺术家搜索列表' elif x == ord('3'): self.data_type = 'albums' self.data_list = ui.build_search('albums') self.title = '专辑搜索列表' elif x == ord('4'): # 搜索结果可以用top_playlists处理 self.data_type = 'top_playlists' self.data_list = ui.build_search('search_playlist') self.title = '精选歌单搜索列表'
class Menu: def __init__(self): reload(sys) sys.setdefaultencoding("UTF-8") self.config = Config() self.datatype = "main" self.title = "网易云音乐" self.datalist = ["排行榜", "艺术家", "新碟上架", "精选歌单", "我的歌单", "DJ节目", "每日推荐", "私人FM", "搜索", "帮助"] self.offset = 0 self.index = 0 self.storage = Storage() self.storage.load() self.collection = self.storage.database["collections"][0] self.player = Player() self.player.playing_song_changed_callback = self.song_changed_callback self.cache = Cache() self.ui = Ui() self.netease = NetEase() self.screen = curses.initscr() self.screen.keypad(1) self.step = 10 self.stack = [] self.djstack = [] self.userid = self.storage.database["user"]["user_id"] self.username = self.storage.database["user"]["nickname"] self.resume_play = True self.at_playing_list = False signal.signal(signal.SIGWINCH, self.change_term) signal.signal(signal.SIGINT, self.send_kill) self.START = time.time() def change_term(self, signum, frame): self.ui.screen.clear() self.ui.screen.refresh() def send_kill(self, signum, fram): self.player.stop() self.cache.quit() self.storage.save() curses.endwin() sys.exit() def alert(self, version): latest = Menu().check_version() if latest != version: if platform.system() == "Darwin": os.system( '/usr/bin/osascript -e \'display notification "MusicBox Update is available"sound name "/System/Library/Sounds/Ping.aiff"\'' ) time.sleep(0.5) os.system( "/usr/bin/osascript -e 'display notification \"NetEase-MusicBox installed version:" + version + "\nNetEase-MusicBox latest version:" + latest + "\"'" ) else: os.system('/usr/bin/notify-send "MusicBox Update is available"') def check_version(self): # 检查更新 tree = ET.ElementTree(ET.fromstring(str(self.netease.get_version()))) root = tree.getroot() return root[0][4][0][0].text def start_fork(self, version): # Hong, Fork a child process. # Return 0 in the child and the child’s process id in the parent. pid = os.fork() if pid == 0: Menu().alert(version) else: Menu().start() def play_pause(self): if len(self.storage.database["player_info"]["player_list"]) == 0: return if self.player.pause_flag: self.player.resume() else: self.player.pause() time.sleep(0.1) def next_song(self): if len(self.storage.database["player_info"]["player_list"]) == 0: return self.player.next() time.sleep(0.1) def previous_song(self): if len(self.storage.database["player_info"]["player_list"]) == 0: return self.player.prev() time.sleep(0.1) def start(self): # Hong, Return the time in seconds since the epoch as a floating point number. self.START = time.time() // 1 self.ui.build_menu(self.datatype, self.title, self.datalist, self.offset, self.index, self.step, self.START) self.ui.build_process_bar( self.player.process_location, self.player.process_length, self.player.playing_flag, self.player.pause_flag, self.storage.database["player_info"]["playing_mode"], ) self.stack.append([self.datatype, self.title, self.datalist, self.offset, self.index]) if bind_global: keybinder.bind(self.config.get_item("global_play_pause"), self.play_pause) keybinder.bind(self.config.get_item("global_next"), self.next_song) keybinder.bind(self.config.get_item("global_previous"), self.previous_song) while True: datatype = self.datatype title = self.title datalist = self.datalist offset = self.offset idx = index = self.index step = self.step stack = self.stack djstack = self.djstack self.screen.timeout(500) key = self.screen.getch() if bind_global: keybinder.gtk.main_iteration(False) self.ui.screen.refresh() # term resize if key == -1: self.ui.update_size() self.player.update_size() # 退出 # Hong, ord(), Given a string of length one, return an integer representing the Unicode code point of the character when the argument is a unicode object, # or the value of the byte when the argument is an 8-bit string. if key == ord("q"): break # 退出并清除用户信息 if key == ord("w"): self.storage.database["user"] = {"username": "", "password": "", "user_id": "", "nickname": ""} try: os.remove(self.storage.cookie_path) except: break break # 上移 elif key == ord("k"): # turn page if at beginning if idx == offset: if offset == 0: continue self.offset -= step # 移动光标到最后一列 self.index = offset - 1 else: self.index = carousel(offset, min(len(datalist), offset + step) - 1, idx - 1) self.START = time.time() # 下移 elif key == ord("j"): # turn page if at end if idx == min(len(datalist), offset + step) - 1: if offset + step >= len(datalist): continue self.offset += step # 移动光标到第一列 self.index = offset + step else: self.index = carousel(offset, min(len(datalist), offset + step) - 1, idx + 1) self.START = time.time() # 数字快捷键 elif ord("0") <= key <= ord("9"): if self.datatype == "songs" or self.datatype == "djchannels" or self.datatype == "help": continue idx = key - ord("0") self.ui.build_menu(self.datatype, self.title, self.datalist, self.offset, idx, self.step, self.START) self.ui.build_loading() self.dispatch_enter(idx) self.index = 0 self.offset = 0 # 向上翻页 elif key == ord("u"): if offset == 0: continue self.START = time.time() self.offset -= step # e.g. 23 - 10 = 13 --> 10 self.index = (index - step) // step * step # 向下翻页 elif key == ord("d"): if offset + step >= len(datalist): continue self.START = time.time() self.offset += step # e.g. 23 + 10 = 33 --> 30 self.index = (index + step) // step * step # 前进 elif key == ord("l") or key == 10: if ( self.datatype == "songs" or self.datatype == "djchannels" or self.datatype == "help" or len(self.datalist) <= 0 ): continue self.START = time.time() self.ui.build_loading() self.dispatch_enter(idx) self.index = 0 self.offset = 0 # 回退 elif key == ord("h"): # if not main menu if len(self.stack) == 1: continue self.START = time.time() up = stack.pop() self.datatype = up[0] self.title = up[1] self.datalist = up[2] self.offset = up[3] self.index = up[4] self.at_playing_list = False # 搜索 elif key == ord("f"): # 8 is the 'search' menu self.dispatch_enter(8) # 播放下一曲 elif key == ord("]"): self.next_song() # 播放上一曲 elif key == ord("["): self.previous_song() # 增加音量 elif key == ord("="): self.player.volume_up() # 减少音量 elif key == ord("-"): self.player.volume_down() # 随机播放 elif key == ord("?"): if len(self.storage.database["player_info"]["player_list"]) == 0: continue self.player.shuffle() time.sleep(0.1) # 喜爱 elif key == ord(","): return_data = self.request_api(self.netease.fm_like, self.player.get_playing_id()) if return_data != -1: if platform.system() == "Darwin": os.system("/usr/bin/osascript -e 'display notification \"Added successfully\"'") else: os.system('/usr/bin/notify-send "Added successfully"') # 删除FM elif key == ord("."): if self.datatype == "fmsongs": if len(self.storage.database["player_info"]["player_list"]) == 0: continue self.player.next() return_data = self.request_api(self.netease.fm_trash, self.player.get_playing_id()) if return_data != -1: if platform.system() == "Darwin": os.system("/usr/bin/osascript -e 'display notification \"Deleted successfully\"'") else: os.system('/usr/bin/notify-send "Deleted successfully"') time.sleep(0.1) # 下一FM elif key == ord("/"): if self.datatype == "fmsongs": if len(self.storage.database["player_info"]["player_list"]) == 0: continue self.player.next() time.sleep(0.1) # 播放、暂停 elif key == ord(" "): # If not open a new playing list, just play and pause. try: if self.datalist[idx]["song_id"] == self.player.playing_id: self.player.play_and_pause(self.storage.database["player_info"]["idx"]) time.sleep(0.1) continue except: pass # If change to a new playing list. Add playing list and play. if datatype == "songs": self.resume_play = False self.player.new_player_list("songs", self.title, self.datalist, -1) self.player.end_callback = None self.player.play_and_pause(idx) self.at_playing_list = True elif datatype == "djchannels": self.resume_play = False self.player.new_player_list("djchannels", self.title, self.datalist, -1) self.player.end_callback = None self.player.play_and_pause(idx) self.at_playing_list = True elif datatype == "fmsongs": self.resume_play = False self.storage.database["player_info"]["playing_mode"] = 0 self.player.new_player_list("fmsongs", self.title, self.datalist, -1) self.player.end_callback = self.fm_callback self.player.play_and_pause(idx) self.at_playing_list = True else: self.player.play_and_pause(self.storage.database["player_info"]["idx"]) time.sleep(0.1) # 加载当前播放列表 elif key == ord("p"): self.show_playing_song() # 播放模式切换 elif key == ord("P"): self.storage.database["player_info"]["playing_mode"] = ( self.storage.database["player_info"]["playing_mode"] + 1 ) % 5 # 添加到打碟歌单 elif key == ord("a"): if datatype == "songs" and len(datalist) != 0: self.djstack.append(datalist[idx]) elif datatype == "artists": pass # 加载打碟歌单 elif key == ord("z"): self.stack.append([datatype, title, datalist, offset, index]) self.datatype = "songs" self.title = "网易云音乐 > 打碟" self.datalist = self.djstack self.offset = 0 self.index = 0 # 添加到收藏歌曲 elif key == ord("s"): if (datatype == "songs" or datatype == "djchannels") and len(datalist) != 0: self.collection.append(datalist[idx]) if platform.system() == "Darwin": os.system("/usr/bin/osascript -e 'display notification \"Added successfully\"'") else: os.system('/usr/bin/notify-send "Added successfully"') # 加载收藏歌曲 elif key == ord("c"): self.stack.append([datatype, title, datalist, offset, index]) self.datatype = "songs" self.title = "网易云音乐 > 收藏" self.datalist = self.collection self.offset = 0 self.index = 0 # 从当前列表移除 elif key == ord("r"): if (datatype == "songs" or datatype == "djchannels") and len(datalist) != 0: self.datalist.pop(idx) self.index = carousel(offset, min(len(datalist), offset + step) - 1, idx) # 当前项目下移 elif key == ord("J"): if datatype != "main" and len(datalist) != 0 and idx + 1 != len(self.datalist): self.START = time.time() song = self.datalist.pop(idx) self.datalist.insert(idx + 1, song) self.index = idx + 1 # 翻页 if self.index >= offset + step: self.offset = offset + step # 当前项目上移 elif key == ord("K"): if datatype != "main" and len(datalist) != 0 and idx != 0: self.START = time.time() song = self.datalist.pop(idx) self.datalist.insert(idx - 1, song) self.index = idx - 1 # 翻页 if self.index < offset: self.offset = offset - step elif key == ord("m"): if datatype != "main": self.stack.append([datatype, title, datalist, offset, index]) self.datatype = self.stack[0][0] self.title = self.stack[0][1] self.datalist = self.stack[0][2] self.offset = 0 self.index = 0 elif key == ord("g"): if datatype == "help": webbrowser.open_new_tab("https://github.com/darknessomi/musicbox") # 开始下载 elif key == ord("C"): s = self.datalist[idx] cache_thread = threading.Thread( target=self.player.cacheSong1time, args=(s["song_id"], s["song_name"], s["artist"], s["mp3_url"]) ) cache_thread.start() elif key == ord("i"): if self.player.playing_id != -1: webbrowser.open_new_tab("http://music.163.com/#/song?id=" + str(self.player.playing_id)) self.ui.build_process_bar( self.player.process_location, self.player.process_length, self.player.playing_flag, self.player.pause_flag, self.storage.database["player_info"]["playing_mode"], ) self.ui.build_menu(self.datatype, self.title, self.datalist, self.offset, self.index, self.step, self.START) self.player.stop() self.cache.quit() self.storage.save() curses.endwin() def dispatch_enter(self, idx): # The end of stack netease = self.netease datatype = self.datatype title = self.title datalist = self.datalist offset = self.offset index = self.index self.stack.append([datatype, title, datalist, offset, index]) if datatype == "main": self.choice_channel(idx) # 该艺术家的热门歌曲 elif datatype == "artists": artist_id = datalist[idx]["artist_id"] songs = netease.artists(artist_id) self.datatype = "songs" self.datalist = netease.dig_info(songs, "songs") self.title += " > " + datalist[idx]["artists_name"] # 该专辑包含的歌曲 elif datatype == "albums": album_id = datalist[idx]["album_id"] songs = netease.album(album_id) self.datatype = "songs" self.datalist = netease.dig_info(songs, "songs") self.title += " > " + datalist[idx]["albums_name"] # 精选歌单选项 elif datatype == "playlists": data = self.datalist[idx] self.datatype = data["datatype"] self.datalist = netease.dig_info(data["callback"](), self.datatype) self.title += " > " + data["title"] # 全站置顶歌单包含的歌曲 elif datatype == "top_playlists": log.debug(datalist) playlist_id = datalist[idx]["playlist_id"] songs = netease.playlist_detail(playlist_id) self.datatype = "songs" self.datalist = netease.dig_info(songs, "songs") self.title += " > " + datalist[idx]["playlists_name"] # 分类精选 elif datatype == "playlist_classes": # 分类名称 data = self.datalist[idx] self.datatype = "playlist_class_detail" self.datalist = netease.dig_info(data, self.datatype) self.title += " > " + data log.debug(self.datalist) # 某一分类的详情 elif datatype == "playlist_class_detail": # 子类别 data = self.datalist[idx] self.datatype = "top_playlists" self.datalist = netease.dig_info(netease.top_playlists(data), self.datatype) log.debug(self.datalist) self.title += " > " + data # 歌曲榜单 elif datatype == "toplists": songs = netease.top_songlist(idx) self.title += " > " + self.datalist[idx] self.datalist = netease.dig_info(songs, "songs") self.datatype = "songs" # 搜索菜单 elif datatype == "search": ui = self.ui # no need to do stack.append, Otherwise there will be a bug when you input key 'h' to return # if idx in range(1, 5): # self.stack.append([self.datatype, self.title, self.datalist, self.offset, self.index]) self.index = 0 self.offset = 0 if idx == 0: # 搜索结果可以用top_playlists处理 self.datatype = "top_playlists" self.datalist = ui.build_search("search_playlist") self.title = "精选歌单搜索列表" elif idx == 1: self.datatype = "songs" self.datalist = ui.build_search("songs") self.title = "歌曲搜索列表" elif idx == 2: self.datatype = "artists" self.datalist = ui.build_search("artists") self.title = "艺术家搜索列表" elif idx == 3: self.datatype = "albums" self.datalist = ui.build_search("albums") self.title = "专辑搜索列表" def show_playing_song(self): if len(self.storage.database["player_info"]["player_list"]) == 0: return if not self.at_playing_list: self.stack.append([self.datatype, self.title, self.datalist, self.offset, self.index]) self.at_playing_list = True self.datatype = self.storage.database["player_info"]["player_list_type"] self.title = self.storage.database["player_info"]["player_list_title"] self.datalist = [] for i in self.storage.database["player_info"]["player_list"]: self.datalist.append(self.storage.database["songs"][i]) self.index = self.storage.database["player_info"]["idx"] self.offset = self.storage.database["player_info"]["idx"] / self.step * self.step if self.resume_play: if self.datatype == "fmsongs": self.player.end_callback = self.fm_callback else: self.player.end_callback = None self.storage.database["player_info"]["idx"] = -1 self.player.play_and_pause(self.index) self.resume_play = False def song_changed_callback(self): if self.at_playing_list: self.show_playing_song() def fm_callback(self): log.debug("FM CallBack.") data = self.get_new_fm() self.player.append_songs(data) if self.datatype == "fmsongs": if len(self.storage.database["player_info"]["player_list"]) == 0: return self.datatype = self.storage.database["player_info"]["player_list_type"] self.title = self.storage.database["player_info"]["player_list_title"] self.datalist = [] for i in self.storage.database["player_info"]["player_list"]: self.datalist.append(self.storage.database["songs"][i]) self.index = self.storage.database["player_info"]["idx"] self.offset = self.storage.database["player_info"]["idx"] / self.step * self.step def request_api(self, func, *args): if self.storage.database["user"]["user_id"] != "": result = func(*args) if result != -1: return result log.debug("Re Login.") user_info = {} if self.storage.database["user"]["username"] != "": user_info = self.netease.login( self.storage.database["user"]["username"], self.storage.database["user"]["password"] ) if self.storage.database["user"]["username"] == "" or user_info["code"] != 200: data = self.ui.build_login() # 取消登录 if data == -1: return -1 user_info = data[0] self.storage.database["user"]["username"] = data[1][0] self.storage.database["user"]["password"] = data[1][1] self.storage.database["user"]["user_id"] = user_info["account"]["id"] self.storage.database["user"]["nickname"] = user_info["profile"]["nickname"] self.userid = self.storage.database["user"]["user_id"] self.username = self.storage.database["user"]["nickname"] return func(*args) def get_new_fm(self): myplaylist = [] for count in range(0, 1): data = self.request_api(self.netease.personal_fm) if data == -1: break myplaylist += data time.sleep(0.2) return self.netease.dig_info(myplaylist, "fmsongs") def choice_channel(self, idx): # 排行榜 netease = self.netease if idx == 0: self.datalist = netease.return_toplists() self.title += " > 排行榜" self.datatype = "toplists" # 艺术家 elif idx == 1: artists = netease.top_artists() self.datalist = netease.dig_info(artists, "artists") self.title += " > 艺术家" self.datatype = "artists" # 新碟上架 elif idx == 2: albums = netease.new_albums() self.datalist = netease.dig_info(albums, "albums") self.title += " > 新碟上架" self.datatype = "albums" # 精选歌单 elif idx == 3: self.datalist = [ {"title": "全站置顶", "datatype": "top_playlists", "callback": netease.top_playlists}, {"title": "分类精选", "datatype": "playlist_classes", "callback": netease.playlist_classes}, ] self.title += " > 精选歌单" self.datatype = "playlists" # 我的歌单 elif idx == 4: myplaylist = self.request_api(self.netease.user_playlist, self.userid) if myplaylist == -1: return self.datatype = "top_playlists" self.datalist = netease.dig_info(myplaylist, self.datatype) self.title += " > " + self.username + " 的歌单" # DJ节目 elif idx == 5: self.datatype = "djchannels" self.title += " > DJ节目" self.datalist = netease.djchannels() # 每日推荐 elif idx == 6: self.datatype = "songs" self.title += " > 每日推荐" myplaylist = self.request_api(self.netease.recommend_playlist) if myplaylist == -1: return self.datalist = self.netease.dig_info(myplaylist, self.datatype) # 私人FM elif idx == 7: self.datatype = "fmsongs" self.title += " > 私人FM" self.datalist = self.get_new_fm() # 搜索 elif idx == 8: self.datatype = "search" self.title += " > 搜索" self.datalist = ["歌曲", "艺术家", "专辑", "网易精选集"] # 帮助 elif idx == 9: self.datatype = "help" self.title += " > 帮助" self.datalist = shortcut self.offset = 0 self.index = 0
class Menu: def __init__(self): reload(sys) sys.setdefaultencoding('UTF-8') self.datatype = 'main' self.title = '网易云音乐' self.datalist = ['排行榜', '艺术家', '新碟上架', '精选歌单', '我的歌单', 'DJ节目', '打碟', '收藏', '搜索', '帮助'] self.offset = 0 self.index = 0 self.presentsongs = [] self.player = Player() self.ui = Ui() self.netease = NetEase() self.screen = curses.initscr() self.screen.keypad(1) self.step = STEP self.stack = [] self.djstack = [] self.userid = None self.username = None try: sfile = file(home + "/netease-musicbox/flavor.json",'r') data = json.loads(sfile.read()) self.collection = data['collection'] self.account = data['account'] sfile.close() except: self.collection = [] self.account = {} def start(self): self.ui.build_menu(self.datatype, self.title, self.datalist, self.offset, self.index, self.step) self.stack.append([self.datatype, self.title, self.datalist, self.offset, self.index]) while True: datatype = self.datatype title = self.title datalist = self.datalist offset = self.offset idx = index = self.index step = self.step stack = self.stack djstack = self.djstack key = self.screen.getch() self.ui.screen.refresh() # 退出 if key == ord('q'): break # 上移 elif key == ord('k'): self.index = carousel(offset, min( len(datalist), offset + step) - 1, idx-1 ) # 下移 elif key == ord('j'): self.index = carousel(offset, min( len(datalist), offset + step) - 1, idx+1 ) # 向上翻页 elif key == ord('u'): if offset == 0: continue self.offset -= step # e.g. 23 - 10 = 13 --> 10 self.index = (index-step)//step*step # 向下翻页 elif key == ord('d'): if offset + step >= len( datalist ): continue self.offset += step # e.g. 23 + 10 = 33 --> 30 self.index = (index+step)//step*step # 前进 elif key == ord('l') or key == 10: if self.datatype == 'songs' or self.datatype == 'djchannels' or self.datatype == 'help': continue self.ui.build_loading() self.dispatch_enter(idx) self.index = 0 self.offset = 0 # 回退 elif key == ord('h'): # if not main menu if len(self.stack) == 1: continue up = stack.pop() self.datatype = up[0] self.title = up[1] self.datalist = up[2] self.offset = up[3] self.index = up[4] # 搜索 elif key == ord('f'): self.search() # 播放下一曲 elif key == ord(']'): if len(self.presentsongs) == 0: continue self.player.next() time.sleep(0.1) # 播放上一曲 elif key == ord('['): if len(self.presentsongs) == 0: continue self.player.prev() time.sleep(0.1) # 播放、暂停 elif key == ord(' '): if datatype == 'songs': self.presentsongs = ['songs', title, datalist, offset, index] elif datatype == 'djchannels': self.presentsongs = ['djchannels', title, datalist, offset, index] self.player.play(datatype, datalist, idx) time.sleep(0.1) # 加载当前播放列表 elif key == ord('p'): if len(self.presentsongs) == 0: continue self.stack.append( [datatype, title, datalist, offset, index] ) self.datatype = self.presentsongs[0] self.title = self.presentsongs[1] self.datalist = self.presentsongs[2] self.offset = self.presentsongs[3] self.index = self.presentsongs[4] # 添加到打碟歌单 elif key == ord('a'): if datatype == 'songs' and len(datalist) != 0: self.djstack.append( datalist[idx] ) elif datatype == 'artists': pass # 加载打碟歌单 elif key == ord('z'): self.stack.append( [datatype, title, datalist, offset, index] ) self.datatype = 'songs' self.title = '网易云音乐 > 打碟' self.datalist = self.djstack self.offset = 0 self.index = 0 # 添加到收藏歌曲 elif key == ord('s'): if (datatype == 'songs' or datatype == 'djchannels') and len(datalist) != 0: self.collection.append( datalist[idx] ) # 加载收藏歌曲 elif key == ord('c'): self.stack.append( [datatype, title, datalist, offset, index] ) self.datatype = 'songs' self.title = '网易云音乐 > 收藏' self.datalist = self.collection self.offset = 0 self.index = 0 # 从当前列表移除 elif key == ord('r'): if datatype != 'main' and len(datalist) != 0: self.datalist.pop(idx) self.index = carousel(offset, min( len(datalist), offset + step) - 1, idx ) elif key == ord('m'): if datatype != 'main': self.stack.append( [datatype, title, datalist, offset, index] ) self.datatype = self.stack[0][0] self.title = self.stack[0][1] self.datalist = self.stack[0][2] self.offset = 0 self.index = 0 elif key == ord('g'): if datatype == 'help': webbrowser.open_new_tab('https://github.com/vellow/NetEase-MusicBox') elif key == ord('w'): if datatype == 'songs': self.player.download() self.ui.build_menu(self.datatype, self.title, self.datalist, self.offset, self.index, self.step) self.player.stop() sfile = file(home + "/netease-musicbox/flavor.json", 'w') data = { 'account': self.account, 'collection': self.collection } sfile.write(json.dumps(data)) sfile.close() curses.endwin() def dispatch_enter(self, idx): # The end of stack netease = self.netease datatype = self.datatype title = self.title datalist = self.datalist offset = self.offset index = self.index self.stack.append( [datatype, title, datalist, offset, index]) if datatype == 'main': self.choice_channel(idx) # 该艺术家的热门歌曲 elif datatype == 'artists': artist_id = datalist[idx]['artist_id'] songs = netease.artists(artist_id) self.datatype = 'songs' self.datalist = netease.dig_info(songs, 'songs') self.title += ' > ' + datalist[idx]['artists_name'] # 该专辑包含的歌曲 elif datatype == 'albums': album_id = datalist[idx]['album_id'] songs = netease.album(album_id) self.datatype = 'songs' self.datalist = netease.dig_info(songs, 'songs') self.title += ' > ' + datalist[idx]['albums_name'] # 该歌单包含的歌曲 elif datatype == 'playlists': playlist_id = datalist[idx]['playlist_id'] songs = netease.playlist_detail(playlist_id) self.datatype = 'songs' self.datalist = netease.dig_info(songs, 'songs') self.title += ' > ' + datalist[idx]['playlists_name'] def choice_channel(self, idx): # 排行榜 netease = self.netease if idx == 0: songs = netease.top_songlist() self.datalist = netease.dig_info(songs, 'songs') self.title += ' > 排行榜' self.datatype = 'songs' # 艺术家 elif idx == 1: artists = netease.top_artists() self.datalist = netease.dig_info(artists, 'artists') self.title += ' > 艺术家' self.datatype = 'artists' # 新碟上架 elif idx == 2: albums = netease.new_albums() self.datalist = netease.dig_info(albums, 'albums') self.title += ' > 新碟上架' self.datatype = 'albums' # 精选歌单 elif idx == 3: playlists = netease.top_playlists() self.datalist = netease.dig_info(playlists, 'playlists') self.title += ' > 精选歌单' self.datatype = 'playlists' # 我的歌单 elif idx == 4: # 未登录 if self.userid is None: # 使用本地存储了账户登录 if self.account: user_info = netease.login(self.account[0], self.account[1]) # 本地没有存储账户,或本地账户失效,则引导录入 if self.account == {} or user_info['code'] != 200: data = self.ui.build_login() # 取消登录 if data == -1: return user_info = data[0] self.account = data[1] self.username = user_info['profile']['nickname'] self.userid = user_info['account']['id'] # 读取登录之后的用户歌单 myplaylist = netease.user_playlist( self.userid ) self.datalist = netease.dig_info(myplaylist, 'playlists') self.datatype = 'playlists' self.title += ' > ' + self.username + ' 的歌单' # DJ节目 elif idx == 5: self.datatype = 'djchannels' self.title += ' > DJ节目' self.datalist = netease.djchannels() # 打碟 elif idx == 6: self.datatype = 'songs' self.title += ' > 打碟' self.datalist = self.djstack # 收藏 elif idx == 7: self.datatype = 'songs' self.title += ' > 收藏' self.datalist = self.collection # 搜索 elif idx == 8: self.search() # 帮助 elif idx == 9: self.datatype = 'help' self.title += ' > 帮助' self.datalist = shortcut self.offset = 0 self.index = 0 def search(self): ui = self.ui x = ui.build_search_menu() # if do search, push current info into stack if x in range(ord('1'), ord('5')): self.stack.append( [self.datatype, self.title, self.datalist, self.offset, self.index ]) self.index = 0 self.offset = 0 if x == ord('1'): self.datatype = 'songs' self.datalist = ui.build_search('songs') self.title = '歌曲搜索列表' elif x == ord('2'): self.datatype = 'artists' self.datalist = ui.build_search('artists') self.title = '艺术家搜索列表' elif x == ord('3'): self.datatype = 'albums' self.datalist = ui.build_search('albums') self.title = '专辑搜索列表' elif x == ord('4'): self.datatype = 'playlists' self.datalist = ui.build_search('playlists') self.title = '精选歌单搜索列表'
class Player: def __init__(self): self.ui = Ui() self.datatype = 'songs' self.popen_handler = None # flag stop, prevent thread start self.playing_flag = False self.pause_flag = False self.songs = [] self.idx = 0 def popen_recall(self, onExit, popenArgs): """ Runs the given args in a subprocess.Popen, and then calls the function onExit when the subprocess completes. onExit is a callable object, and popenArgs is a lists/tuple of args that would give to subprocess.Popen. """ def runInThread(onExit, popenArgs): self.popen_handler = subprocess.Popen(['mpg123', popenArgs], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE) self.popen_handler.wait() if self.playing_flag: self.idx = carousel(0, len(self.songs)-1, self.idx+1 ) onExit() return thread = threading.Thread(target=runInThread, args=(onExit, popenArgs)) thread.start() # returns immediately after the thread starts return thread def notify(self, item, executable='notify-send'): try: cover_path = os.path.expanduser('~') + \ '/netease-musicbox/cover.jpg' song_info = "%s-%s \n %s" \ % (item['album_name'], item['song_name'], item['artist']) with open(os.devnull, 'w') as fnull: handler = subprocess.Popen(['curl', item['cover_url'], '-o', cover_path], stdout=fnull, stderr=subprocess.STDOUT) handler.wait() handler = subprocess.Popen(['convert', cover_path, '-resize', '150x150', cover_path], stdout=fnull, stderr=subprocess.STDOUT) handler.wait() handler = subprocess.Popen(['notify-send', '-i', cover_path, '-t', '3000', song_info], stdout=fnull, stderr=subprocess.STDOUT) except: pass def recall(self): self.playing_flag = True item = self.songs[ self.idx ] self.ui.build_playinfo(item['song_name'], item['artist'], item['album_name'], bitrate=item['bitrate']) self.notify(item) self.popen_recall(self.recall, item['mp3_url']) def play(self, datatype, songs, idx): # if same playlists && idx --> same song :: pause/resume it self.datatype = datatype if datatype == 'songs' or datatype == 'djchannels': if idx == self.idx and songs == self.songs: if self.pause_flag: self.resume() else: self.pause() else: if datatype == 'songs' or datatype == 'djchannels': self.songs = songs self.idx = idx # if it's playing if self.playing_flag: self.switch() # start new play else: self.recall() # if current menu is not song, pause/resume else: if self.playing_flag: if self.pause_flag: self.resume() else: self.pause() else: pass # play another def switch(self): self.stop() # wait process be killed time.sleep(0.01) self.recall() def stop(self): if self.playing_flag and self.popen_handler: self.playing_flag = False self.popen_handler.kill() def pause(self): self.pause_flag = True os.kill(self.popen_handler.pid, signal.SIGSTOP) item = self.songs[ self.idx ] self.ui.build_playinfo(item['song_name'], item['artist'], item['album_name'], bitrate=item['bitrate'], pause=True) def resume(self): self.pause_flag = False os.kill(self.popen_handler.pid, signal.SIGCONT) item = self.songs[ self.idx ] self.ui.build_playinfo(item['song_name'], item['artist'], item['album_name'], bitrate=item['bitrate']) def next(self): self.stop() time.sleep(0.01) self.idx = carousel(0, len(self.songs)-1, self.idx+1 ) self.recall() def prev(self): self.stop() time.sleep(0.01) self.idx = carousel(0, len(self.songs)-1, self.idx-1 ) self.recall()
class Player: def __init__(self): self.config = Config() self.ui = Ui() self.popen_handler = None # flag stop, prevent thread start self.playing_flag = False self.pause_flag = False self.process_length = 0 self.process_location = 0 self.process_first = False self.storage = Storage() self.info = self.storage.database["player_info"] self.songs = self.storage.database["songs"] self.playing_id = -1 self.cache = Cache() self.notifier = self.config.get_item("notifier") self.mpg123_parameters = self.config.get_item("mpg123_parameters") self.end_callback = None self.playing_song_changed_callback = None def popen_recall(self, onExit, popenArgs): """ Runs the given args in subprocess.Popen, and then calls the function onExit when the subprocess completes. onExit is a callable object, and popenArgs is a lists/tuple of args that would give to subprocess.Popen. """ def runInThread(onExit, arg): para = ['mpg123', '-R'] para[1:1] = self.mpg123_parameters self.popen_handler = subprocess.Popen(para, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE) self.popen_handler.stdin.write("V " + str(self.info[ "playing_volume"]) + "\n") if arg: self.popen_handler.stdin.write("L " + arg + "\n") else: self.next_idx() onExit() return self.process_first = True while True: if self.playing_flag is False: break strout = self.popen_handler.stdout.readline() if re.match("^\@F.*$", strout): process_data = strout.split(" ") process_location = float(process_data[4]) if self.process_first: self.process_length = process_location self.process_first = False self.process_location = 0 else: self.process_location = self.process_length - process_location # NOQA continue elif strout[:2] == '@E': # get a alternative url from new api sid = popenArgs['song_id'] new_url = NetEase().songs_detail_new_api([sid])[0]['url'] if new_url is None: log.warning(('Song {} is unavailable ' 'due to copyright issue').format(sid)) break log.error('Song {} is not compatible with old api.'.format( sid)) self.popen_handler.stdin.write("\nL " + new_url + "\n") self.popen_handler.stdout.readline() elif strout == "@P 0\n": self.popen_handler.stdin.write("Q\n") self.popen_handler.kill() break if self.playing_flag: self.next_idx() onExit() return def getLyric(): if 'lyric' not in self.songs[str(self.playing_id)].keys(): self.songs[str(self.playing_id)]["lyric"] = [] if len(self.songs[str(self.playing_id)]["lyric"]) > 0: return netease = NetEase() lyric = netease.song_lyric(self.playing_id) if lyric == [] or lyric == '未找到歌词': return lyric = lyric.split('\n') self.songs[str(self.playing_id)]["lyric"] = lyric return def gettLyric(): if 'tlyric' not in self.songs[str(self.playing_id)].keys(): self.songs[str(self.playing_id)]["tlyric"] = [] if len(self.songs[str(self.playing_id)]["tlyric"]) > 0: return netease = NetEase() tlyric = netease.song_tlyric(self.playing_id) if tlyric == [] or tlyric == '未找到歌词翻译': return tlyric = tlyric.split('\n') self.songs[str(self.playing_id)]["tlyric"] = tlyric return def cacheSong(song_id, song_name, artist, song_url): def cacheExit(song_id, path): self.songs[str(song_id)]['cache'] = path self.cache.add(song_id, song_name, artist, song_url, cacheExit) self.cache.start_download() if 'cache' in popenArgs.keys() and os.path.isfile(popenArgs['cache']): thread = threading.Thread(target=runInThread, args=(onExit, popenArgs['cache'])) else: thread = threading.Thread(target=runInThread, args=(onExit, popenArgs['mp3_url'])) cache_thread = threading.Thread( target=cacheSong, args=(popenArgs['song_id'], popenArgs['song_name'], popenArgs[ 'artist'], popenArgs['mp3_url'])) cache_thread.start() thread.start() lyric_download_thread = threading.Thread(target=getLyric, args=()) lyric_download_thread.start() tlyric_download_thread = threading.Thread(target=gettLyric, args=()) tlyric_download_thread.start() # returns immediately after the thread starts return thread def get_playing_id(self): return self.playing_id def recall(self): if self.info["idx"] >= len(self.info["player_list"]) and self.end_callback is not None: self.end_callback() if self.info["idx"] < 0 or self.info["idx"] >= len(self.info["player_list"]): self.info["idx"] = 0 self.stop() return self.playing_flag = True self.pause_flag = False item = self.songs[self.info["player_list"][self.info["idx"]]] self.ui.build_playinfo(item['song_name'], item['artist'], item['album_name'], item['quality'], time.time()) if self.notifier: self.ui.notify("Now playing", item['song_name'], item['album_name'], item['artist']) self.playing_id = item['song_id'] self.popen_recall(self.recall, item) def generate_shuffle_playing_list(self): del self.info["playing_list"][:] for i in range(0, len(self.info["player_list"])): self.info["playing_list"].append(i) random.shuffle(self.info["playing_list"]) self.info["ridx"] = 0 def new_player_list(self, type, title, datalist, offset): self.info["player_list_type"] = type self.info["player_list_title"] = title self.info["idx"] = offset del self.info["player_list"][:] del self.info["playing_list"][:] self.info["ridx"] = 0 for song in datalist: self.info["player_list"].append(str(song["song_id"])) if str(song["song_id"]) not in self.songs.keys(): self.songs[str(song["song_id"])] = song else: database_song = self.songs[str(song["song_id"])] if (database_song["song_name"] != song["song_name"] or database_song["quality"] != song["quality"]): self.songs[str(song["song_id"])] = song def append_songs(self, datalist): for song in datalist: self.info["player_list"].append(str(song["song_id"])) if str(song["song_id"]) not in self.songs.keys(): self.songs[str(song["song_id"])] = song else: database_song = self.songs[str(song["song_id"])] if database_song["song_name"] != song["song_name"] or \ database_song["quality"] != song["quality"] or \ database_song["mp3_url"] != song["mp3_url"]: if "cache" in self.songs[str(song["song_id"])].keys(): song["cache"] = self.songs[str(song["song_id"])][ "cache"] self.songs[str(song["song_id"])] = song if len(datalist) > 0 and self.info["playing_mode"] == 3 or self.info[ "playing_mode"] == 4: self.generate_shuffle_playing_list() def play_and_pause(self, idx): # if same playlists && idx --> same song :: pause/resume it if self.info["idx"] == idx: if self.pause_flag: self.resume() else: self.pause() else: self.info["idx"] = idx # if it's playing if self.playing_flag: self.switch() # start new play else: self.recall() # play another def switch(self): self.stop() # wait process be killed time.sleep(0.1) self.recall() def stop(self): if self.playing_flag and self.popen_handler: self.playing_flag = False self.popen_handler.stdin.write("Q\n") try: self.popen_handler.kill() except OSError as e: log.error(e) return def pause(self): if not self.playing_flag and not self.popen_handler: return self.pause_flag = True self.popen_handler.stdin.write("P\n") item = self.songs[self.info["player_list"][self.info["idx"]]] self.ui.build_playinfo(item['song_name'], item['artist'], item['album_name'], item['quality'], time.time(), pause=True) def resume(self): self.pause_flag = False self.popen_handler.stdin.write("P\n") item = self.songs[self.info["player_list"][self.info["idx"]]] self.ui.build_playinfo(item['song_name'], item['artist'], item['album_name'], item['quality'], time.time()) self.playing_id = item['song_id'] def _swap_song(self): plist = self.info["playing_list"] now_songs = plist.index(self.info["idx"]) plist[0], plist[now_songs] = plist[now_songs], plist[0] def _is_idx_valid(self): return 0 <= self.info["idx"] < len(self.info["player_list"]) def _inc_idx(self): if self.info["idx"] < len(self.info["player_list"]) - 1: self.info["idx"] += 1 def _dec_idx(self): if self.info["idx"] > 0: self.info["idx"] -= 1 def next_idx(self): if not self._is_idx_valid(): self.stop() return playlist_len = len(self.info["player_list"]) playinglist_len = len(self.info["playing_list"]) # Playing mode. 0 is ordered. 1 is orderde loop. # 2 is single song loop. 3 is single random. 4 is random loop if self.info["playing_mode"] == 0: self._inc_idx() elif self.info["playing_mode"] == 1: self.info["idx"] = (self.info["idx"] + 1) % playlist_len elif self.info["playing_mode"] == 2: self.info["idx"] = self.info["idx"] elif self.info["playing_mode"] == 3 or self.info["playing_mode"] == 4: # First is out of border. Second is change playlist. if self.info["ridx"] >= playinglist_len or self.info["playing_list"][self.info["ridx"]] != self.info["idx"]: self.generate_shuffle_playing_list() playinglist_len = len(self.info["playing_list"]) # When you regenerate playing list, you should keep previous song same. try: self._swap_song() except Exception as e: log.error(e) self.info["ridx"] += 1 # Out of border if self.info["playing_mode"] == 4: self.info["ridx"] %= playinglist_len if self.info["ridx"] >= playinglist_len: self.info["idx"] = playlist_len else: self.info["idx"] = self.info["playing_list"][self.info["ridx"]] else: self.info["idx"] += 1 if self.playing_song_changed_callback is not None: self.playing_song_changed_callback() def next(self): self.stop() time.sleep(0.01) self.next_idx() self.recall() def prev_idx(self): if not self._is_idx_valid(): self.stop() return playlist_len = len(self.info["player_list"]) playinglist_len = len(self.info["playing_list"]) # Playing mode. 0 is ordered. 1 is orderde loop. # 2 is single song loop. 3 is single random. 4 is random loop if self.info["playing_mode"] == 0: self._dec_idx() elif self.info["playing_mode"] == 1: self.info["idx"] = (self.info["idx"] - 1) % playlist_len elif self.info["playing_mode"] == 2: self.info["idx"] = self.info["idx"] elif self.info["playing_mode"] == 3 or self.info["playing_mode"] == 4: if self.info["ridx"] >= len(self.info["playing_list"]) or \ self.info["playing_list"][self.info["ridx"]] != self.info["idx"]: self.generate_shuffle_playing_list() playinglist_len = len(self.info["playing_list"]) self.info["ridx"] -= 1 if self.info["ridx"] < 0: if self.info["playing_mode"] == 3: self.info["ridx"] = 0 else: self.info["ridx"] %= playinglist_len self.info["idx"] = self.info["playing_list"][self.info["ridx"]] else: self.info["idx"] -= 1 if self.playing_song_changed_callback is not None: self.playing_song_changed_callback() def prev(self): self.stop() time.sleep(0.01) self.prev_idx() self.recall() def shuffle(self): self.stop() time.sleep(0.01) self.info["playing_mode"] = 3 self.generate_shuffle_playing_list() self.info["idx"] = self.info["playing_list"][self.info["ridx"]] self.recall() def volume_up(self): self.info["playing_volume"] = self.info["playing_volume"] + 7 if (self.info["playing_volume"] > 100): self.info["playing_volume"] = 100 if not self.playing_flag: return self.popen_handler.stdin.write("V " + str(self.info[ "playing_volume"]) + "\n") def volume_down(self): self.info["playing_volume"] = self.info["playing_volume"] - 7 if (self.info["playing_volume"] < 0): self.info["playing_volume"] = 0 if not self.playing_flag: return self.popen_handler.stdin.write("V " + str(self.info[ "playing_volume"]) + "\n") def update_size(self): try: self.ui.update_size() item = self.songs[self.info["player_list"][self.info["idx"]]] if self.playing_flag: self.ui.build_playinfo(item['song_name'], item['artist'], item['album_name'], item['quality'], time.time()) if self.pause_flag: self.ui.build_playinfo(item['song_name'], item['artist'], item['album_name'], item['quality'], time.time(), pause=True) except Exception as e: log.error(e) pass def cacheSong1time(self, song_id, song_name, artist, song_url): def cacheExit(song_id, path): self.songs[str(song_id)]['cache'] = path self.cache.enable = False self.cache.enable = True self.cache.add(song_id, song_name, artist, song_url, cacheExit) self.cache.start_download()
class Player: def __init__(self): self.ui = Ui() self.datatype = 'songs' self.popen_handler = None # flag stop, prevent thread start self.playing_flag = False self.pause_flag = False self.songs = [] self.idx = 0 self.volume = 60 def popen_recall(self, onExit, popenArgs): """ Runs the given args in a subprocess.Popen, and then calls the function onExit when the subprocess completes. onExit is a callable object, and popenArgs is a lists/tuple of args that would give to subprocess.Popen. """ def runInThread(onExit, popenArgs): self.popen_handler = subprocess.Popen(['mpg123', '-R', ], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE) self.popen_handler.stdin.write("SILENCE\n") self.popen_handler.stdin.write("V " + str(self.volume) + "\n") self.popen_handler.stdin.write("L " + popenArgs + "\n") # self.popen_handler.wait() while (True): if self.playing_flag == False: break try: strout = self.popen_handler.stdout.readline() except IOError: break if strout == "@P 0\n": self.popen_handler.stdin.write("Q\n") self.popen_handler.kill() break if self.playing_flag: self.idx = carousel(0, len(self.songs) - 1, self.idx + 1) onExit() return thread = threading.Thread(target=runInThread, args=(onExit, popenArgs)) thread.start() # returns immediately after the thread starts return thread def recall(self): self.playing_flag = True item = self.songs[self.idx] self.ui.build_playinfo(item['song_name'], item['artist'], item['album_name'], item['quality'], time.time()) self.popen_recall(self.recall, item['mp3_url']) def play(self, datatype, songs, idx): # if same playlists && idx --> same song :: pause/resume it self.datatype = datatype if datatype == 'songs' or datatype == 'djchannels': if idx == self.idx and songs == self.songs: if self.pause_flag: self.resume() else: self.pause() else: if datatype == 'songs' or datatype == 'djchannels': self.songs = songs self.idx = idx # if it's playing if self.playing_flag: self.switch() # start new play else: self.recall() # if current menu is not song, pause/resume else: if self.playing_flag: if self.pause_flag: self.resume() else: self.pause() else: pass # play another def switch(self): self.stop() # wait process be killed time.sleep(0.01) self.recall() def stop(self): if self.playing_flag and self.popen_handler: self.playing_flag = False self.popen_handler.stdin.write("Q\n") self.popen_handler.kill() def pause(self): self.pause_flag = True os.kill(self.popen_handler.pid, signal.SIGSTOP) item = self.songs[self.idx] self.ui.build_playinfo(item['song_name'], item['artist'], item['album_name'], item['quality'], time.time(), pause=True) def resume(self): self.pause_flag = False os.kill(self.popen_handler.pid, signal.SIGCONT) item = self.songs[self.idx] self.ui.build_playinfo(item['song_name'], item['artist'], item['album_name'], item['quality'], time.time()) def next(self): self.stop() time.sleep(0.01) self.idx = carousel(0, len(self.songs) - 1, self.idx + 1) self.recall() def prev(self): self.stop() time.sleep(0.01) self.idx = carousel(0, len(self.songs) - 1, self.idx - 1) self.recall() def shuffle(self): self.stop() time.sleep(0.01) num = random.randint(0, 12) self.idx = carousel(0, len(self.songs) - 1, self.idx + num) self.recall() def volume_up(self): self.volume = self.volume + 7 if (self.volume > 100): self.volume = 100 self.popen_handler.stdin.write("V " + str(self.volume) + "\n") def volume_down(self): self.volume = self.volume - 7 if (self.volume < 0): self.volume = 0 self.popen_handler.stdin.write("V " + str(self.volume) + "\n") def update_size(self): try: self.ui.update_size() item = self.songs[self.idx] if self.playing_flag: self.ui.build_playinfo(item['song_name'], item['artist'], item['album_name'], item['quality'], time.time()) if self.pause_flag: self.ui.build_playinfo(item['song_name'], item['artist'], item['album_name'], item['quality'], time.time(), pause=True) except IndexError: pass
class Player: def __init__(self): self.ui = Ui() self.datatype = 'songs' self.popen_handler = None # flag stop, prevent thread start self.playing_flag = False self.pause_flag = False self.songs = [] self.idx = 0 def popen_recall(self, onExit, popenArgs): """ Runs the given args in a subprocess.Popen, and then calls the function onExit when the subprocess completes. onExit is a callable object, and popenArgs is a lists/tuple of args that would give to subprocess.Popen. """ def runInThread(onExit, popenArgs): self.popen_handler = subprocess.Popen(['mpg123', popenArgs], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE) self.popen_handler.wait() if self.playing_flag: self.idx = carousel(0, len(self.songs)-1, self.idx+1 ) onExit() return thread = threading.Thread(target=runInThread, args=(onExit, popenArgs)) thread.start() # returns immediately after the thread starts return thread def recall(self): self.playing_flag = True item = self.songs[ self.idx ] self.ui.build_playinfo(item['song_name'], item['artist'], item['album_name']) self.popen_recall(self.recall, item['mp3_url']) def play(self, datatype, songs, idx): # if same playlists && idx --> same song :: pause/resume it self.datatype = datatype if datatype == 'songs' or datatype == 'djchannels': if idx == self.idx and songs == self.songs: if self.pause_flag: self.resume() else: self.pause() else: if datatype == 'songs' or datatype == 'djchannels': self.songs = songs self.idx = idx # if it's playing if self.playing_flag: self.switch() # start new play else: self.recall() # if current menu is not song, pause/resume else: if self.playing_flag: if self.pause_flag: self.resume() else: self.pause() else: pass # play another def switch(self): self.stop() # wait process be killed time.sleep(0.01) self.recall() def stop(self): if self.playing_flag and self.popen_handler: self.playing_flag = False self.popen_handler.kill() def pause(self): self.pause_flag = True os.kill(self.popen_handler.pid, signal.SIGSTOP) item = self.songs[ self.idx ] self.ui.build_playinfo(item['song_name'], item['artist'], item['album_name'], pause=True) def resume(self): self.pause_flag = False os.kill(self.popen_handler.pid, signal.SIGCONT) item = self.songs[ self.idx ] self.ui.build_playinfo(item['song_name'], item['artist'], item['album_name']) def next(self): self.stop() time.sleep(0.01) self.idx = carousel(0, len(self.songs)-1, self.idx+1 ) self.recall() def prev(self): self.stop() time.sleep(0.01) self.idx = carousel(0, len(self.songs)-1, self.idx-1 ) self.recall()
class Menu: def __init__(self): reload(sys) sys.setdefaultencoding('UTF-8') self.config = Config() self.datatype = 'main' self.title = '网易云音乐' self.datalist = ['排行榜', '艺术家', '新碟上架', '精选歌单', '我的歌单', 'DJ节目', '每日推荐', '私人FM', '搜索', '帮助'] self.offset = 0 self.index = 0 self.storage = Storage() self.storage.load() self.collection = self.storage.database['collections'][0] self.player = Player() self.player.playing_song_changed_callback = self.song_changed_callback self.cache = Cache() self.ui = Ui() self.netease = NetEase() self.screen = curses.initscr() self.screen.keypad(1) self.step = 10 self.stack = [] self.djstack = [] self.userid = self.storage.database["user"]["user_id"] self.username = self.storage.database["user"]["nickname"] self.resume_play = True self.at_playing_list = False signal.signal(signal.SIGWINCH, self.change_term) signal.signal(signal.SIGINT, self.send_kill) self.START = time.time() def change_term(self, signum, frame): self.ui.screen.clear() self.ui.screen.refresh() def send_kill(self, signum, fram): self.player.stop() self.cache.quit() self.storage.save() curses.endwin() sys.exit() def update_alert(self, version): latest = Menu().check_version() if latest != version and latest != 0: if platform.system() == 'Darwin': os.system('/usr/bin/osascript -e \'display notification "MusicBox Update is available"sound name "/System/Library/Sounds/Ping.aiff"\'') time.sleep(0.5) os.system('/usr/bin/osascript -e \'display notification "NetEase-MusicBox installed version:' + version + '\nNetEase-MusicBox latest version:' + latest + '"\'') else: os.system('/usr/bin/notify-send "MusicBox Update is available"') def signin_alert(self, type): if type == 0: if platform.system() == 'Darwin': os.system('/usr/bin/osascript -e \'display notification "Mobile signin success"sound name "/System/Library/Sounds/Ping.aiff"\'') else: os.system('/usr/bin/notify-send "Mobile signin success"') else: if platform.system() == 'Darwin': os.system('/usr/bin/osascript -e \'display notification "PC signin success"sound name "/System/Library/Sounds/Ping.aiff"\'') else: os.system('/usr/bin/notify-send "PC signin success"') def check_version(self): # 检查更新 && 签到 try: mobilesignin = self.netease.daily_signin(0) if mobilesignin != -1 and mobilesignin['code'] != -2: self.signin_alert(0) time.sleep(0.5) pcsignin = self.netease.daily_signin(1) if pcsignin != -1 and pcsignin['code'] != -2: self.signin_alert(1) tree = ET.ElementTree(ET.fromstring(str(self.netease.get_version()))) root = tree.getroot() return root[0][4][0][0].text except: return 0 def start_fork(self, version): pid = os.fork() if pid == 0: Menu().update_alert(version) else: Menu().start() def play_pause(self): if len(self.storage.database["player_info"]["player_list"]) == 0: return if self.player.pause_flag: self.player.resume() else: self.player.pause() time.sleep(0.1) def next_song(self): if len(self.storage.database["player_info"]["player_list"]) == 0: return self.player.next() time.sleep(0.1) def previous_song(self): if len(self.storage.database["player_info"]["player_list"]) == 0: return self.player.prev() time.sleep(0.1) def start(self): self.START = time.time() // 1 self.ui.build_menu(self.datatype, self.title, self.datalist, self.offset, self.index, self.step, self.START) self.ui.build_process_bar(self.player.process_location, self.player.process_length, self.player.playing_flag, self.player.pause_flag, self.storage.database['player_info']['playing_mode']) self.stack.append([self.datatype, self.title, self.datalist, self.offset, self.index]) if bind_global: keybinder.bind(self.config.get_item("global_play_pause"), self.play_pause) keybinder.bind(self.config.get_item("global_next"), self.next_song) keybinder.bind(self.config.get_item("global_previous"), self.previous_song) while True: datatype = self.datatype title = self.title datalist = self.datalist offset = self.offset idx = index = self.index step = self.step stack = self.stack djstack = self.djstack self.screen.timeout(500) key = self.screen.getch() if bind_global: keybinder.gtk.main_iteration(False) self.ui.screen.refresh() # term resize if key == -1: self.ui.update_size() self.player.update_size() # 退出 if key == ord('q'): break # 退出并清除用户信息 if key == ord('w'): self.storage.database['user'] = { "username": "", "password": "", "user_id": "", "nickname": "", } try: os.remove(self.storage.cookie_path) except: break break # 上移 elif key == ord('k'): # turn page if at beginning if idx == offset: if offset == 0: continue self.offset -= step # 移动光标到最后一列 self.index = offset - 1 else: self.index = carousel(offset, min( len(datalist), offset + step) - 1, idx - 1) self.START = time.time() # 下移 elif key == ord('j'): # turn page if at end if idx == min( len(datalist), offset + step) - 1: if offset + step >= len( datalist ): continue self.offset += step # 移动光标到第一列 self.index = offset + step else: self.index = carousel(offset, min( len(datalist), offset + step) - 1, idx + 1) self.START = time.time() # 数字快捷键 elif ord('0') <= key <= ord('9'): if self.datatype == 'songs' or self.datatype == 'djchannels' or self.datatype == 'help': continue idx = key - ord('0') self.ui.build_menu(self.datatype, self.title, self.datalist, self.offset, idx, self.step, self.START) self.ui.build_loading() self.dispatch_enter(idx) self.index = 0 self.offset = 0 # 向上翻页 elif key == ord('u'): if offset == 0: continue self.START = time.time() self.offset -= step # e.g. 23 - 10 = 13 --> 10 self.index = (index - step) // step * step # 向下翻页 elif key == ord('d'): if offset + step >= len(datalist): continue self.START = time.time() self.offset += step # e.g. 23 + 10 = 33 --> 30 self.index = (index + step) // step * step # 前进 elif key == ord('l') or key == 10: if self.datatype == 'songs' or self.datatype == 'djchannels' or self.datatype == 'help' or len(self.datalist) <= 0: continue self.START = time.time() self.ui.build_loading() self.dispatch_enter(idx) self.index = 0 self.offset = 0 # 回退 elif key == ord('h'): # if not main menu if len(self.stack) == 1: continue self.START = time.time() up = stack.pop() self.datatype = up[0] self.title = up[1] self.datalist = up[2] self.offset = up[3] self.index = up[4] self.at_playing_list = False # 搜索 elif key == ord('f'): # 8 is the 'search' menu self.dispatch_enter(8) # 播放下一曲 elif key == ord(']'): self.next_song() # 播放上一曲 elif key == ord('['): self.previous_song() # 增加音量 elif key == ord('='): self.player.volume_up() # 减少音量 elif key == ord('-'): self.player.volume_down() # 随机播放 elif key == ord('?'): if len(self.storage.database["player_info"]["player_list"]) == 0: continue self.player.shuffle() time.sleep(0.1) # 喜爱 elif key == ord(','): return_data = self.request_api(self.netease.fm_like, self.player.get_playing_id()) if return_data != -1: if platform.system() == 'Darwin': os.system('/usr/bin/osascript -e \'display notification "Added successfully"\'') else: os.system('/usr/bin/notify-send "Added successfully"') # 删除FM elif key == ord('.'): if self.datatype == 'fmsongs': if len(self.storage.database["player_info"]["player_list"]) == 0: continue self.player.next() return_data = self.request_api(self.netease.fm_trash, self.player.get_playing_id()) if return_data != -1: if platform.system() == 'Darwin': os.system('/usr/bin/osascript -e \'display notification "Deleted successfully"\'') else: os.system('/usr/bin/notify-send "Deleted successfully"') time.sleep(0.1) # 下一FM elif key == ord('/'): if self.datatype == 'fmsongs': if len(self.storage.database["player_info"]["player_list"]) == 0: continue self.player.next() time.sleep(0.1) # 播放、暂停 elif key == ord(' '): # If not open a new playing list, just play and pause. try: if self.datalist[idx]['song_id'] == self.player.playing_id: self.player.play_and_pause(self.storage.database['player_info']['idx']) time.sleep(0.1) continue except: pass # If change to a new playing list. Add playing list and play. if datatype == 'songs': self.resume_play = False self.player.new_player_list('songs', self.title, self.datalist, -1) self.player.end_callback = None self.player.play_and_pause(idx) self.at_playing_list = True elif datatype == 'djchannels': self.resume_play = False self.player.new_player_list('djchannels', self.title, self.datalist, -1) self.player.end_callback = None self.player.play_and_pause(idx) self.at_playing_list = True elif datatype == 'fmsongs': self.resume_play = False self.storage.database['player_info']['playing_mode'] = 0 self.player.new_player_list('fmsongs', self.title, self.datalist, -1) self.player.end_callback = self.fm_callback self.player.play_and_pause(idx) self.at_playing_list = True else: self.player.play_and_pause(self.storage.database['player_info']['idx']) time.sleep(0.1) # 加载当前播放列表 elif key == ord('p'): self.show_playing_song() # 播放模式切换 elif key == ord('P'): self.storage.database['player_info']['playing_mode'] = \ (self.storage.database['player_info']['playing_mode'] + 1) % 5 # 添加到打碟歌单 elif key == ord('a'): if datatype == 'songs' and len(datalist) != 0: self.djstack.append(datalist[idx]) elif datatype == 'artists': pass # 加载打碟歌单 elif key == ord('z'): self.stack.append([datatype, title, datalist, offset, index]) self.datatype = 'songs' self.title = '网易云音乐 > 打碟' self.datalist = self.djstack self.offset = 0 self.index = 0 # 添加到收藏歌曲 elif key == ord('s'): if (datatype == 'songs' or datatype == 'djchannels') and len(datalist) != 0: self.collection.append(datalist[idx]) if platform.system() == 'Darwin': os.system('/usr/bin/osascript -e \'display notification "Added successfully"\'') else: os.system('/usr/bin/notify-send "Added successfully"') # 加载收藏歌曲 elif key == ord('c'): self.stack.append([datatype, title, datalist, offset, index]) self.datatype = 'songs' self.title = '网易云音乐 > 收藏' self.datalist = self.collection self.offset = 0 self.index = 0 # 从当前列表移除 elif key == ord('r'): if (datatype == 'songs' or datatype == 'djchannels') and len(datalist) != 0: self.datalist.pop(idx) self.index = carousel(offset, min(len(datalist), offset + step) - 1, idx) # 当前项目下移 elif key == ord("J"): if datatype != 'main' and len(datalist) != 0 and idx + 1 != len(self.datalist): self.START = time.time() song = self.datalist.pop(idx) self.datalist.insert(idx + 1, song) self.index = idx + 1 # 翻页 if self.index >= offset + step: self.offset = offset + step # 当前项目上移 elif key == ord("K"): if datatype != 'main' and len(datalist) != 0 and idx != 0: self.START = time.time() song = self.datalist.pop(idx) self.datalist.insert(idx - 1, song) self.index = idx - 1 # 翻页 if self.index < offset: self.offset = offset - step elif key == ord('m'): if datatype != 'main': self.stack.append([datatype, title, datalist, offset, index]) self.datatype = self.stack[0][0] self.title = self.stack[0][1] self.datalist = self.stack[0][2] self.offset = 0 self.index = 0 elif key == ord('g'): if datatype == 'help': webbrowser.open_new_tab('https://github.com/darknessomi/musicbox') # 开始下载 elif key == ord("C"): s = self.datalist[idx] cache_thread = threading.Thread(target=self.player.cacheSong1time, args=( s['song_id'], s['song_name'], s['artist'], s['mp3_url'])) cache_thread.start() elif key == ord('i'): if self.player.playing_id != -1: webbrowser.open_new_tab('http://music.163.com/#/song?id=' + str(self.player.playing_id)) self.ui.build_process_bar(self.player.process_location, self.player.process_length, self.player.playing_flag, self.player.pause_flag, self.storage.database['player_info']['playing_mode']) self.ui.build_menu(self.datatype, self.title, self.datalist, self.offset, self.index, self.step, self.START) self.player.stop() self.cache.quit() self.storage.save() curses.endwin() def dispatch_enter(self, idx): # The end of stack netease = self.netease datatype = self.datatype title = self.title datalist = self.datalist offset = self.offset index = self.index self.stack.append([datatype, title, datalist, offset, index]) if idx > len(self.datalist): return False if datatype == 'main': self.choice_channel(idx) # 该艺术家的热门歌曲 elif datatype == 'artists': artist_id = datalist[idx]['artist_id'] songs = netease.artists(artist_id) self.datatype = 'songs' self.datalist = netease.dig_info(songs, 'songs') self.title += ' > ' + datalist[idx]['artists_name'] # 该专辑包含的歌曲 elif datatype == 'albums': album_id = datalist[idx]['album_id'] songs = netease.album(album_id) self.datatype = 'songs' self.datalist = netease.dig_info(songs, 'songs') self.title += ' > ' + datalist[idx]['albums_name'] # 精选歌单选项 elif datatype == 'playlists': data = self.datalist[idx] self.datatype = data['datatype'] self.datalist = netease.dig_info(data['callback'](), self.datatype) self.title += ' > ' + data['title'] # 全站置顶歌单包含的歌曲 elif datatype == 'top_playlists': log.debug(datalist) playlist_id = datalist[idx]['playlist_id'] songs = netease.playlist_detail(playlist_id) self.datatype = 'songs' self.datalist = netease.dig_info(songs, 'songs') self.title += ' > ' + datalist[idx]['playlists_name'] # 分类精选 elif datatype == 'playlist_classes': # 分类名称 data = self.datalist[idx] self.datatype = 'playlist_class_detail' self.datalist = netease.dig_info(data, self.datatype) self.title += ' > ' + data log.debug(self.datalist) # 某一分类的详情 elif datatype == 'playlist_class_detail': # 子类别 data = self.datalist[idx] self.datatype = 'top_playlists' self.datalist = netease.dig_info(netease.top_playlists(data), self.datatype) log.debug(self.datalist) self.title += ' > ' + data # 歌曲榜单 elif datatype == 'toplists': songs = netease.top_songlist(idx) self.title += ' > ' + self.datalist[idx] self.datalist = netease.dig_info(songs, 'songs') self.datatype = 'songs' # 搜索菜单 elif datatype == 'search': ui = self.ui # no need to do stack.append, Otherwise there will be a bug when you input key 'h' to return # if idx in range(1, 5): # self.stack.append([self.datatype, self.title, self.datalist, self.offset, self.index]) self.index = 0 self.offset = 0 if idx == 0: # 搜索结果可以用top_playlists处理 self.datatype = 'top_playlists' self.datalist = ui.build_search('search_playlist') self.title = '精选歌单搜索列表' elif idx == 1: self.datatype = 'songs' self.datalist = ui.build_search('songs') self.title = '歌曲搜索列表' elif idx == 2: self.datatype = 'artists' self.datalist = ui.build_search('artists') self.title = '艺术家搜索列表' elif idx == 3: self.datatype = 'albums' self.datalist = ui.build_search('albums') self.title = '专辑搜索列表' def show_playing_song(self): if len(self.storage.database['player_info']['player_list']) == 0: return if not self.at_playing_list: self.stack.append([self.datatype, self.title, self.datalist, self.offset, self.index]) self.at_playing_list = True self.datatype = self.storage.database['player_info']['player_list_type'] self.title = self.storage.database['player_info']['player_list_title'] self.datalist = [] for i in self.storage.database['player_info']['player_list']: self.datalist.append(self.storage.database['songs'][i]) self.index = self.storage.database['player_info']['idx'] self.offset = self.storage.database['player_info']['idx'] / self.step * self.step if self.resume_play: if self.datatype == "fmsongs": self.player.end_callback = self.fm_callback else: self.player.end_callback = None self.storage.database['player_info']['idx'] = -1 self.player.play_and_pause(self.index) self.resume_play = False def song_changed_callback(self): if self.at_playing_list: self.show_playing_song() def fm_callback(self): log.debug("FM CallBack.") data = self.get_new_fm() self.player.append_songs(data) if self.datatype == 'fmsongs': if len(self.storage.database['player_info']['player_list']) == 0: return self.datatype = self.storage.database['player_info']['player_list_type'] self.title = self.storage.database['player_info']['player_list_title'] self.datalist = [] for i in self.storage.database['player_info']['player_list']: self.datalist.append(self.storage.database['songs'][i]) self.index = self.storage.database['player_info']['idx'] self.offset = self.storage.database['player_info']['idx'] / self.step * self.step def request_api(self, func, *args): if self.storage.database['user']['user_id'] != "": result = func(*args) if result != -1: return result log.debug("Re Login.") user_info = {} if self.storage.database['user']['username'] != "": user_info = self.netease.login(self.storage.database['user']['username'], self.storage.database['user']['password']) if self.storage.database['user']['username'] == "" or user_info['code'] != 200: data = self.ui.build_login() # 取消登录 if data == -1: return -1 user_info = data[0] self.storage.database['user']['username'] = data[1][0] self.storage.database['user']['password'] = data[1][1] self.storage.database['user']['user_id'] = user_info['account']['id'] self.storage.database['user']['nickname'] = user_info['profile']['nickname'] self.userid = self.storage.database["user"]["user_id"] self.username = self.storage.database["user"]["nickname"] return func(*args) def get_new_fm(self): myplaylist = [] for count in range(0, 1): data = self.request_api(self.netease.personal_fm) if data == -1: break myplaylist += data time.sleep(0.2) return self.netease.dig_info(myplaylist, "fmsongs") def choice_channel(self, idx): # 排行榜 netease = self.netease if idx == 0: self.datalist = netease.return_toplists() self.title += ' > 排行榜' self.datatype = 'toplists' # 艺术家 elif idx == 1: artists = netease.top_artists() self.datalist = netease.dig_info(artists, 'artists') self.title += ' > 艺术家' self.datatype = 'artists' # 新碟上架 elif idx == 2: albums = netease.new_albums() self.datalist = netease.dig_info(albums, 'albums') self.title += ' > 新碟上架' self.datatype = 'albums' # 精选歌单 elif idx == 3: self.datalist = [ { 'title': '全站置顶', 'datatype': 'top_playlists', 'callback': netease.top_playlists }, { 'title': '分类精选', 'datatype': 'playlist_classes', 'callback': netease.playlist_classes } ] self.title += ' > 精选歌单' self.datatype = 'playlists' # 我的歌单 elif idx == 4: myplaylist = self.request_api(self.netease.user_playlist, self.userid) if myplaylist == -1: return self.datatype = 'top_playlists' self.datalist = netease.dig_info(myplaylist, self.datatype) self.title += ' > ' + self.username + ' 的歌单' # DJ节目 elif idx == 5: self.datatype = 'djchannels' self.title += ' > DJ节目' self.datalist = netease.djchannels() # 每日推荐 elif idx == 6: self.datatype = 'songs' self.title += ' > 每日推荐' myplaylist = self.request_api(self.netease.recommend_playlist) if myplaylist == -1: return self.datalist = self.netease.dig_info(myplaylist, self.datatype) # 私人FM elif idx == 7: self.datatype = 'fmsongs' self.title += ' > 私人FM' self.datalist = self.get_new_fm() # 搜索 elif idx == 8: self.datatype = 'search' self.title += ' > 搜索' self.datalist = ['歌曲', '艺术家', '专辑', '网易精选集'] # 帮助 elif idx == 9: self.datatype = 'help' self.title += ' > 帮助' self.datalist = shortcut self.offset = 0 self.index = 0
def main(): open_canvas() global mainback mainback = Mainback() global start start = False while(start == False): handle_events() clear_canvas() mainback.draw() update_canvas() delay(0.08) #클래스 선언 global hero hero = Hero() rabbit = Rabbit() rabbit_group = [Rabbit() for i in range(600)] land = Land() wood = Wood() global torch torch = Torch() global fire fire = Fire() eskimo = Eskimo() attack_fire = Attack_fire() attack_fire_group = [Attack_fire() for i in range(100)] background = BackGround() global ui ui = Ui() firewood = Firewood() firewood_group = [Firewood() for i in range(600)] #변수 선언 rabbit_group_counter = 0 rabbit_group_collision_counter = 0 attack_group_counter = 0 attack_group_update_counter = 0 attack_group_collision_counter = 0 rabbit_alive_counter = 0 attack_group_alive_check = False attack_group_alive_counter = 0 attack_group_limit = 20 rabbit_group_draw_counter = 0 firewood_num_counter = 0 firewood_num_update_counter = 0 firewood_collide_counter = 0 rabbit_group_counter2 = 0 rabbit_jump = False rabbit_num = 10 firewood_num = 10 rack_block = 0 eskimo_counter = 0 global running running = True while running: #핸들 이벤트 handle_events() #업데이트 hero.update() background.update() land.update() wood.update() fire.update() torch.update() eskimo.update() ui.update(hero.x, hero.y, hero.ability) for rabbit in rabbit_group: # 토끼 업데이트 if(rabbit_group_counter == rabbit_num): rabbit_group_counter = 0 break if(rabbit.alive): rabbit.update() rabbit_group_counter += 1 # for rabbit in rabbit_group: # 토끼 업데이트 # if(rabbit_group_counter2 == 1): # print("%d" % rabbit.x) # break # rabbit_group_counter2 += 1 for attack_fire in attack_fire_group: # 공격불 업데이트 if(attack_group_update_counter == hero.attack_num): attack_fire.init_direction() attack_fire.alive = True # 공격불이 활성화 됨 attack_fire.init_fire() attack_group_update_counter = 0 break if(attack_fire.alive): attack_fire.update() attack_group_update_counter += 1 for firewood in firewood_group: # 장작 업데이트 if(firewood_num_update_counter == firewood_num): firewood_num_update_counter = 0 break firewood.update() firewood_num_update_counter += 1 #함수 for rabbit in rabbit_group: #토끼와 히어로의 충돌체크 if(rabbit_group_collision_counter == rabbit_num): rabbit_group_collision_counter = 0 break if(collision(rabbit, hero)): rabbit.y += 50 mainback.hero_die = True mainback.die_sound() running = False rabbit_group_collision_counter += 1 for rabbit in rabbit_group: # 토끼와 공격불의 충돌체크 if(rack_block == rabbit_num): rack_block = 0 break for attack_fire in attack_fire_group: if(attack_group_collision_counter == hero.attack_num): attack_group_collision_counter = 0 break if(collision(rabbit, attack_fire) and rabbit.alive and attack_fire.alive): attack_fire.alive = False rabbit.alive = False rabbit.die = True hero.kill += 1 attack_fire.die = False attack_group_collision_counter += 1 rack_block += 1 for attack_fire in attack_fire_group: if(eskimo_counter == hero.attack_num): eskimo_counter = 0 break if(collision(eskimo, attack_fire)): attack_fire.alive = False eskimo.x -= 10 eskimo.hp -= 1 if(eskimo.hp == 0): mainback.eskimo_die = True running = False mainback.win_sound() attack_fire.die = False eskimo_counter += 1 if(collision(wood, hero)): # 나무와 주인공 충돌체크 fire.collide = True if(ui.firewood_num != 0): fire.life += ui.firewood_num*250 ui.firewood_num = 0 else: fire.collide = False if(collision(eskimo, hero)): # 주인공과 에스키모 충돌체크 mainback.hero_die = True running = False mainback.die_sound() for firewood in firewood_group: # 장작과 주인공 충돌체크 if(firewood_collide_counter == firewood_num): firewood_collide_counter = 0 break if(collision(firewood, hero) and firewood.die == False): ui.firewood_num += 1 firewood.die = True firewood_collide_counter += 1 for rabbit in rabbit_group: # 토끼 출현! if(rabbit_alive_counter == rabbit_num): break if(rabbit.die == False): rabbit.alive = True rabbit_alive_counter += 1 if(fire.die): # 불이 꺼지면 토끼들이 마구마구 몰려온다. rabbit_num = 500 for attack_fire in attack_fire_group: # 불 스킬 존재 유무 if(attack_fire.alive): attack_group_alive_counter = 0 break attack_group_alive_counter += 1 if(attack_group_alive_counter == hero.attack_num): hero.attack_num = 0 for attack_fire in attack_fire_group: # 화면 밖을 벗어나면 불 스킬 사망 판정 if(attack_fire.x >= 900 or attack_fire.x <= -100): attack_fire.alive = False print("stage = %d" % background.stage) #스테이지 if(hero.kill == 10 and background.stage == 1): print("+++++++++++++++++++++++++++++++++++++++++++++++++++++++++") rabbit_num += 20 hero.ability += 10 firewood_num += 5 background.stage = 2 if(hero.kill == 30 and background.stage == 2): rabbit_num += 30 firewood_num += 10 hero.ability += 10 background.stage = 3 background.stage3_music() if(hero.kill == 60 and background.stage == 3): rabbit_num += 40 firewood_num += 15 hero.ability += 10 background.stage = 4 if(hero.kill == 80 and background.stage == 4): rabbit_num += 50 firewood_num += 20 hero.ability += 10 background.stage = 5 eskimo.alive = True background.stage5_music() if(background.stage == 5): rabbit_jump = True if(rabbit_jump): for rabbit in rabbit_group: rabbit.y += 5 # print("%d" % hero.attack_num) print("킬 수 : %d num : %d" % (hero.kill, rabbit_num)) clear_canvas() #그리기 background.draw() fire.draw() wood.draw() torch.draw() hero.draw() eskimo.draw() # eskimo.draw_bb() # hero.draw_bb() for rabbit in rabbit_group: # 적토끼 출력 if(rabbit_group_draw_counter == rabbit_num): rabbit_group_draw_counter = 0 break if(rabbit.alive): rabbit.draw() rabbit_group_draw_counter += 1 # rabbit.draw_bb() for attack_fire in attack_fire_group: # 공격 불 출력 if(attack_group_counter == hero.attack_num): attack_group_counter = 0 break if(attack_fire.alive): attack_fire.draw() # attack_fire.draw_bb() attack_group_counter += 1 for firewood in firewood_group: # 장작 출력 if(firewood_num_counter == firewood_num): firewood_num_counter = 0 break firewood.draw() firewood_num_counter += 1 land.draw() ui.draw() update_canvas() delay(0.06) while(mainback.hero_die or mainback.eskimo_die): handle_events() clear_canvas() mainback.draw() update_canvas() delay(0.08) close_canvas()