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 = {}
Exemple #2
0
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()
Exemple #3
0
    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 = {}
Exemple #4
0
    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()
Exemple #5
0
    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
Exemple #6
0
 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)
Exemple #7
0
 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'
Exemple #9
0
    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)
Exemple #11
0
 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()
Exemple #12
0
 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)
Exemple #13
0
 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)
Exemple #14
0
 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()
Exemple #16
0
 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")
Exemple #17
0
 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)
Exemple #18
0
 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()
Exemple #19
0
    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)
Exemple #20
0
 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)
Exemple #22
0
 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)
Exemple #25
0
    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()
Exemple #26
0
 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")
Exemple #27
0
 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)
Exemple #28
0
 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)
Exemple #29
0
    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:")
Exemple #30
0
 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.')
Exemple #31
0
 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()
Exemple #32
0
 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 = {}
Exemple #33
0
    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
Exemple #34
0
 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()
Exemple #35
0
    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()
Exemple #36
0
    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 = {}
Exemple #37
0
 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()
Exemple #39
0
 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
Exemple #40
0
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
Exemple #41
0
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)
Exemple #42
0
 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)  #临时文件``
Exemple #43
0
 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")
Exemple #45
0
 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
Exemple #46
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")
Exemple #47
0
	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)
Exemple #48
0
 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 = {}
Exemple #49
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.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
Exemple #50
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
Exemple #51
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
Exemple #52
0
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
Exemple #54
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 = '精选歌单搜索列表'
Exemple #55
0
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()
Exemple #56
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.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()
Exemple #57
0
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
Exemple #58
0
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()
Exemple #59
0
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
Exemple #60
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()