class Menu

Constants

WAIT_TIME

Attributes

netease[RW]
player[RW]
screen[RW]
ui[RW]

Public Class Methods

new() click to toggle source
# File lib/mdisc/menu.rb, line 31
def initialize
  self.player = Player.new
  self.ui = Ui.new
  self.netease = NetEase.new
  self.screen = ui.screen
  @datatype = 'main'
  @title = '网易云音乐'
  @datalist = %w(排行榜 精选歌单 艺术家 新碟上架 我的歌单 DJ节目 本地收藏 搜索 帮助)
  @offset = 0
  @index = 0
  @present_songs = []
  @step = 25
  @stack = []
  @userid = nil
  @username = nil
  @collection = []
  @playlists = []
  @account = {}
  @carousel = ->(left, right, x){x < left ? right : (x > right ? left : x)}
end

Public Instance Methods

choice_channel(idx) click to toggle source
# File lib/mdisc/menu.rb, line 252
def choice_channel(idx)
  case idx
  # Top
  when 0
    songs = netease.top_songlist
    @datalist = netease.dig_info(songs, 'songs')
    @title += ' > 排行榜'
    @datatype = 'songs'

  # Playlists
  when 1
    playlists = netease.top_playlists
    @datalist = netease.dig_info(playlists, 'playlists')
    @title += ' > 精选歌单'
    @datatype = 'playlists'

  # Artist
  when 2
    artists = netease.top_artists
    @datalist = netease.dig_info(artists, 'artists')
    @title += ' > 艺术家'
    @datatype = 'artists'

  # New album
  when 3
    albums = netease.new_albums
    @datalist = netease.dig_info(albums, 'albums')
    @title += ' > 新碟上架'
    @datatype = 'albums'

  # My playlist
  when 4
    # Require user's account before fetching his playlists.
    check_user_id

    # Fetch this user's all playlists while he logs in successfully.
    my_playlist = netease.user_playlists @userid
    @datalist = netease.dig_info(my_playlist, 'playlists')
    @datatype = 'playlists'
    @title += " > #{@username} 的歌单"

  # DJ channels
  when 5
    @datatype = 'djchannels'
    @title += ' > DJ 节目'
    @datalist = netease.djchannels

  # Favorite things
  when 6
    favorite

  # Search
  when 7
    search

  # Help
  when 8
    @datatype = 'help'
    @title += ' > 帮助'
    @datalist = SHORTCUT
  end

  @offset = 0
  @index = 0
end
dispatch_enter(idx) click to toggle source
# File lib/mdisc/menu.rb, line 214
def dispatch_enter(idx)
  datatype = @datatype
  title = @title
  datalist = @datalist
  offset = @offset
  index = @index
  @stack.push [datatype, title, datalist, offset, index]

  case datatype
  when 'main'
    choice_channel idx

  # Hot songs to which a artist belongs.
  when 'artists'
    id = datalist[idx]['artist_id']
    songs = netease.artists id
    @datatype = 'songs'
    @datalist = netease.dig_info(songs, 'songs')
    @title += " > #{datalist[idx]['aritsts_name']}"

  # All songs to which an album belongs.
  when 'albums'
    id = datalist[idx]['album_id']
    songs = netease.album id
    @datatype = 'songs'
    @datalist = netease.dig_info(songs, 'songs')
    @title += " > #{datalist[idx]['albums_name']}"

  # All songs to which a playlist belongs.
  when 'playlists'
    id = datalist[idx]['playlist_id']
    songs = netease.playlist_detail id
    @datatype = 'songs'
    @datalist = netease.dig_info(songs, 'songs')
    @title += " > #{datalist[idx]['playlists_name']}"
  end
end
favorite() click to toggle source
# File lib/mdisc/menu.rb, line 318
def favorite
  x = ui.build_favorite_menu

  if (1..4).include? x.to_i
    @stack.push [@datatype, @title, @datalist, @offset, @index]
    @index = 0
    @offset = 0
  end

  case x
  when '1'
    @datatype = 'songs'
    @datalist = @collection
    @title += ' > 收藏歌曲'

  when '2'
    @datatype = 'playlists'
    @datalist = @playlists
    @title += ' > 收藏歌单'

  when '3'
    @datatype = 'albums'
    @datalist = @albums
    @title += ' > 收藏专辑'

  when '4'
    @datatype = 'djchannels'
    @datalist = @djs
    @title += ' > 收藏 DJ 节目'

  end
end
start() click to toggle source
# File lib/mdisc/menu.rb, line 52
def start
  check_player
  read_data

  ui.build_menu(@datatype, @title, @datalist, @offset, @index, @step)
  @stack.push [@datatype, @title, @datalist, @offset, @index, @step]

  loop do
    datatype = @datatype
    title = @title
    datalist = @datalist
    offset = @offset
    idx = index = @index
    step = @step
    stack = @stack
    key = screen.getch
    screen.refresh

    case key

    # Quit
    when 'q'
      break

    # Up
    when 'k'
      @index = @carousel[@offset, [datalist.size, offset+step].min - 1, idx - 1]

    # Down
    when 'j'
      @index = @carousel[@offset, [datalist.size, offset+step].min - 1, idx + 1]

    # Previous page
    when 'u'
      next if offset == 0
      @offset = @offset - step
      @index = (index - step).divmod(step)[0] * step

    # Next page
    when 'd'
      next if offset + step >= datalist.size
      @offset = @offset + step
      @index = (index + step).divmod(step)[0] * step

    # If highlighted item is a menu or playlists, just enter it.
    # If highlighted item is a song or an dj channel, just play it.
    when 'l'
      next if @datatype == 'help'
      if @datatype == 'songs' || @datatype == 'djchannels'
        player.play(@datatype, datalist, @index, true)
        @present_songs = [datatype, title, datalist, offset, index]
      else
        ui.build_loading
        dispatch_enter idx
        @index = 0
        @offset = 0
      end

    # Back
    when 'h'
      next if @stack.size == 1
      up = stack.pop
      @datatype, @title, @datalist, @offset, @index = up[0], up[1], up[2], up[3], up[4]

    # Search
    when 'f'
      search

    # Next song
    when ']'
      player.next
      sleep WAIT_TIME

    # Previous song
    when '['
      player.prev
      sleep WAIT_TIME

    # Play or pause a song.
    when ' '
      player.play(datatype, datalist, idx)
      sleep WAIT_TIME

    # Load present playlist.
    when 'p'
      next if @present_songs.empty?
      @stack.push [datatype, title, datalist, offset, index]
      @datatype, @title, @datalist, @offset, @index = @present_songs[0], @present_songs[1], @present_songs[2], @present_songs[3], @present_songs[4]

    # Star a song, a playlist or an album.
    when 's'
      next if datalist.empty?
      if datatype == 'songs'
        @collection.push(datalist[idx]).uniq!
      elsif datatype == 'playlists'
        @playlists.push(datalist[idx]).uniq!
      elsif datatype == 'albums'
        @albums.push(datalist[idx]).uniq!
      elsif datatype == 'djchannels'
        @djs.push(datalist[idx]).uniq!
      end

    # Load favorite playlists.
    when 't'
      @stack.push [datatype, title, datalist, offset, index]
      @datatype = 'playlists'
      @title = '网易云音乐 > 收藏精选歌单'
      @datalist = @playlists
      @offset = 0
      @index = 0

    # Load favorite songs.
    when 'c'
      @stack.push [datatype, title, datalist, offset, index]
      @datatype = 'songs'
      @title = '网易云音乐 > 收藏歌曲列表'
      @datalist = @collection
      @offset = 0
      @index = 0

    # Load favorite albums.
    when 'a'
      @stack.push [datatype, title, datalist, offset, index]
      @datatype = 'albums'
      @title = '网易云音乐 > 收藏专辑'
      @datalist = @albums
      @offset = 0
      @index = 0

    # Load favorite dj channels.
    when 'z'
      @stack.push [datatype, title, datalist, offset, index]
      @datatype = 'djchannels'
      @title = '网易云音乐 > 收藏 DJ 节目'
      @datalist = @djs
      @offset = 0
      @index = 0

    # Remove an entry from the present list.
    when 'r'
      next if datatype == 'main' || datalist.empty?
      @datalist.delete_at idx
      @index = @carousel[@offset, [datalist.size, offset+step].min - 1, idx]

    # Main menu
    when 'm'
      next if datatype == 'main'
      @stack.push [datatype, title, datalist, offset, index]
      @datatype, @title, @datalist = @stack[0][0], @stack[0][1], @stack[0][2]
      @offset = 0
      @index = 0

    end

    write_data
    ui.build_menu(@datatype, @title, @datalist, @offset, @index, @step)
  end

  player.stop
  exit
end

Private Instance Methods

check_dir() click to toggle source
# File lib/mdisc/menu.rb, line 391
def check_dir
  dir = "#{ENV['HOME']}/.mdisc"
  unless Dir.exist? dir
    Dir.mkdir dir
  end
end
check_player() click to toggle source
# File lib/mdisc/menu.rb, line 385
def check_player
  if !system('which mpg123 > /dev/null 2>&1')
    raise '!!!Please install `mpg123` before using Mdisc!!!'
  end
end
check_user_id() click to toggle source
# File lib/mdisc/menu.rb, line 430
def check_user_id
  if !@userid
    user_info = netease.login(@account[0], @account[1]) unless @account.empty?

    if @account == {} || user_info['code'] != 200
      data = ui.build_login
      return if data == -1
      user_info, @account = data[0], data[1]
    end

    @username = user_info['profile']['nickname']
    @userid = user_info['account']['id']
  end
end
read_data() click to toggle source
# File lib/mdisc/menu.rb, line 398
def read_data
  check_dir

  user_file = "#{ENV['HOME']}/.mdisc/flavor.json"
  return unless File.exist? user_file

  data = JSON.parse(File.read(user_file))
  @account = data['account'] || {}
  @collection = data['collection'] || []
  @playlists = data['playlists'] || []
  @albums = data['albums'] || []
  @djs = data['djs'] || []
end
write_data() click to toggle source
# File lib/mdisc/menu.rb, line 412
def write_data
  check_dir

  user_file = "#{ENV['HOME']}/.mdisc/flavor.json"

  data = {
    :account => @account,
    :collection => @collection,
    :playlists => @playlists,
    :albums => @albums,
    :djs => @djs
  }

  File.open(user_file, 'w') do |f|
    f.write(JSON.generate(data))
  end
end