Ejemplo n.º 1
0
def mainCommand():
    try:
        opts, args = getopt.getopt(sys.argv[1:], "ho:l:v:u:p:a:q:r", [
            "help", "output=", "link=", "version", "username", "password",
            "accessToken", "quality", "resolution"
        ])
        link = None
        for opt, val in opts:
            if opt in ('-h', '--help'):
                Printf.usage()
                return
            if opt in ('-v', '--version'):
                Printf.logo()
                return
            if opt in ('-l', '--link'):
                link = val
            if opt in ('-o', '--output'):
                CONF.downloadPath = val
            if opt in ('-u', '--username'):
                USER.username = val
                UserSettings.save(USER)
            if opt in ('-p', '--password'):
                USER.password = val
                UserSettings.save(USER)
            if opt in ('-a', '--accessToken'):
                USER.assesstoken = val
                UserSettings.save(USER)
            if opt in ('-q', '--quality'):
                CONF.audioQuality = Settings.getAudioQuality(val)
            if opt in ('-r', '--resolution'):
                CONF.videoQuality = Settings.getVideoQuality(val)

        if link is None:
            Printf.err(
                "Please enter the link(url/id/path)! Enter 'tidal-dl -h' for help!"
            )
            return
        if not mkdirs(CONF.downloadPath):
            Printf.err(LANG.MSG_PATH_ERR + CONF.downloadPath)
            return

        checkLogin()
        start(USER, CONF, link)
        return
    except getopt.GetoptError:
        Printf.err("Argv error! Enter 'tidal -h' for help!")
Ejemplo n.º 2
0
    def mergerByM3u8_Multithreading(self, url, filepath, showprogress=False, showshell=False):
        """
        #Func    :   多线程下载并合并文件(使用M3u8的url)        
        #Param   :   url             [in] 链接
        #Param   :   filepath        [in] 目标文件名
        #Param   :   showprogress    [in] 是否显示进度条
        #Param   :   showshell       [in] 是否显示cmd信息
        #Return  :   True/False
        """
        try:
            # Get urllist
            urllist = self.__parseM3u8(url)
            if len(urllist) <= 0:
                return False

            # Creat tmpdir
            path    = pathHelper.getDirName(filepath)
            tmpPath = pathHelper.getDiffTmpPathName(path)
            if pathHelper.mkdirs(tmpPath) is False:
                return False
            
            # Progress
            self.progress = None
            if showprogress:
                self.progress = ProgressTool(len(urllist))

            # Download files
            allpath            = []
            self.waitCount     = len(urllist)
            self.completeCount = 0
            for i, item in enumerate(urllist):
                index = i + 100001
                path  = tmpPath + '/' + str(index) + ".ts"
                path  = os.path.abspath(path)
                allpath.append(path)
                if os.path.exists(path):
                    os.remove(path)
                self.thread.start(self.__thradfunc_dl, item, path, 3)
            self.thread.waitAll()
            ret = self.mergerByTs(tmpPath, filepath, showshell)
            # ret = self.mergerByFiles(allpath, filepath, showshell)
            shutil.rmtree(tmpPath)
            return ret
        except:
            return False
Ejemplo n.º 3
0
def mainCommand():
    try:
        opts, args = getopt.getopt(
            sys.argv[1:], "hvl:o:q:r:",
            ["help", "version", "link=", "output=", "quality", "resolution"])
    except getopt.GetoptError as errmsg:
        Printf.err(vars(errmsg)['msg'] + ". Use 'tidal-dl -h' for useage.")
        return

    link = None
    for opt, val in opts:
        if opt in ('-h', '--help'):
            Printf.usage()
            continue
        if opt in ('-v', '--version'):
            Printf.logo()
            continue
        if opt in ('-l', '--link'):
            checkLogin()
            link = val
            continue
        if opt in ('-o', '--output'):
            CONF.downloadPath = val
            Settings.save(CONF)
            continue
        if opt in ('-q', '--quality'):
            CONF.audioQuality = Settings.getAudioQuality(val)
            Settings.save(CONF)
            continue
        if opt in ('-r', '--resolution'):
            CONF.videoQuality = Settings.getVideoQuality(val)
            Settings.save(CONF)
            continue

    if not mkdirs(CONF.downloadPath):
        Printf.err(LANG.MSG_PATH_ERR + CONF.downloadPath)
        return

    if link is not None:
        Printf.info(LANG.SETTING_DOWNLOAD_PATH + ':' + CONF.downloadPath)
        start(TOKEN, CONF, link)
Ejemplo n.º 4
0
 def _downloadFiles(self):
     check = pathHelper.remove(self.tmpPath)
     check = pathHelper.mkdirs(self.tmpPath)
     if self.netVer.mainFile is None:
         return False
     if self.netVer.isZip == 0:
         plist = []
         plist.append(self.netVer.mainFile)
         for item in self.netVer.elseFileList:
             plist.append(item)
         for item in plist:
             urlpath = self.netUrl + '//' + item
             topath = self.tmpPath + '\\' + item
             if netHelper.downloadFile(urlpath, topath) is False:
                 return False
     else:
         urlpath = self.netUrl + '//' + self.netVer.zipFile
         topath = self.tmpPath + '\\' + self.netVer.zipFile
         if netHelper.downloadFile(urlpath, topath) is False:
             return False
         return zipHelper.unzip(topath, self.tmpPath)
     return True
Ejemplo n.º 5
0
def setting():
    cf = TidalConfig()
    print("----------------Settings----------------")
    print("OutputDir    :\t" + cf.outputdir)
    print("SoundQuality :\t" + cf.quality)
    print("Resolution   :\t" + cf.resolution)
    print("ThreadNum    :\t" + cf.threadnum)
    print("OnlyM4a      :\t" + cf.onlym4a)
    print("ShowProgress :\t" + cf.showprogress + "(enable when threadnum=1)")
    print("AddHyphen    :\t" + cf.addhyphen + "(between number and title)")
    while True:
        outputdir = myinput("Outputdir(Enter '0' Unchanged):".ljust(12))
        if outputdir == '0':
            outputdir = cf.outputdir
            break
        if os.path.isdir(outputdir) == False:
            printErr(0, "Path is Err!")
            continue
        break
    while True:
        index = myinputInt(
            "Quality(0-LOW,1-HIGH,2-LOSSLESS,3-HI_RES):".ljust(12), 999)
        if index > 3 or index < 0:
            printErr(0, "Quality Err!")
            continue
        if index == 0:
            quality = 'LOW'
        if index == 1:
            quality = 'HIGH'
        if index == 2:
            quality = 'LOSSLESS'
        if index == 3:
            quality = 'HI_RES'
        break
    while True:
        index = myinputInt(
            "Resolution(0-1080,1-720,2-480,3-360,4-240):".ljust(12), 99)
        if index > 4 or index < 0:
            printErr(0, "Resolution Err")
            continue
        if index == 0:
            resolution = '1080'
        if index == 1:
            resolution = '720'
        if index == 2:
            resolution = '480'
        if index == 3:
            resolution = '360'
        if index == 4:
            resolution = '240'
        break
    while True:
        threadnum = myinput("ThreadNum:".ljust(12))
        if cf.valid_threadnum(threadnum) == False:
            printErr(0, "ThreadNum Err")
            continue
        break
    status = myinputInt("ConvertMp4toM4a(0-False,1-True):".ljust(12), 0)
    status2 = myinputInt("ShowProgress(0-False,1-True):".ljust(12), 0)
    status3 = myinputInt("AddHyphen(0-False,1-True):".ljust(12), 0)

    cf.set_outputdir(outputdir)
    cf.set_quality(quality)
    cf.set_resolution(resolution)
    cf.set_threadnum(threadnum)
    cf.set_onlym4a(status)
    cf.set_showprogress(status2)
    cf.set_addhyphen(status3)

    pathHelper.mkdirs(outputdir + "/Album/")
    pathHelper.mkdirs(outputdir + "/Playlist/")
    pathHelper.mkdirs(outputdir + "/Video/")
    pathHelper.mkdirs(outputdir + "/Favorite/")
    return
Ejemplo n.º 6
0
    def downloadPlaylist(self):
        while True:
            targetDir = self.config.outputdir + "/Playlist/"
            print("--------------PLAYLIST-----------------")
            sID = printChoice("Enter PlayListID(Enter '0' go back):")
            if sID == '0':
                return

            aPlaylistInfo, aItemInfo = self.tool.getPlaylist(sID)
            if self.tool.errmsg != "":
                printErr(0, "Get PlaylistInfo Err! " + self.tool.errmsg)
                return

            print("[Title]                %s" % (aPlaylistInfo['title']))
            print("[Type]                 %s" % (aPlaylistInfo['type']))
            print("[NumberOfTracks]       %s" %
                  (aPlaylistInfo['numberOfTracks']))
            print("[NumberOfVideos]       %s" %
                  (aPlaylistInfo['numberOfVideos']))
            print("[Duration]             %s\n" % (aPlaylistInfo['duration']))

            # Creat OutputDir
            targetDir = targetDir + pathHelper.replaceLimitChar(
                aPlaylistInfo['title'], '-')
            targetDir = os.path.abspath(targetDir)
            pathHelper.mkdirs(targetDir)
            # write msg
            string = self.tool.convertPlaylistInfoToString(
                aPlaylistInfo, aItemInfo)
            with open(targetDir + "/PlaylistInfo.txt", 'w',
                      encoding='utf-8') as fd:
                fd.write(string)

            # download track
            bBreakFlag = False
            bFirstTime = True
            errIndex = []
            index = 0

            while bBreakFlag is False:
                self.check.clear()
                index = 0
                for item in aItemInfo:
                    type = item['type']
                    item = item['item']
                    if type != 'track':
                        continue

                    index = index + 1
                    if bFirstTime is False:
                        if self.check.isInErr(index - 1, errIndex) == False:
                            continue

                    streamInfo = self.tool.getStreamUrl(
                        str(item['id']), self.config.quality)
                    if self.tool.errmsg != "":
                        printErr(
                            14, item['title'] + "(Get Stream Url Err!!" +
                            self.tool.errmsg + ")")
                        continue

                    fileType = self._getSongExtension(streamInfo['url'])
                    filePath = targetDir + '/' + pathHelper.replaceLimitChar(
                        item['title'], '-') + fileType
                    paraList = {
                        'index': index,
                        'title': item['title'],
                        'trackinfo': item,
                        'url': streamInfo['url'],
                        'path': filePath,
                        'retry': 3,
                        'key': streamInfo['encryptionKey']
                    }
                    self.check.addPath(filePath)
                    if not os.path.isfile(filePath):
                        self.thread.start(self.__thradfunc_dl, paraList)
                self.thread.waitAll()
                self.tool.removeTmpFile(targetDir)

                bBreakFlag = True
                bFirstTime = False

                # check
                isErr, errIndex = self.check.checkPaths()
                if isErr:
                    check = printChoice(
                        "[Err]\t\t" + len(errIndex) +
                        " Tracks Download Failed.Try Again?(y/n):")
                    if check == 'y' or check == 'Y':
                        bBreakFlag = False

            # download video
            for item in aItemInfo:
                type = item['type']
                item = item['item']
                if type != 'video':
                    continue

                filePath = targetDir + '/' + pathHelper.replaceLimitChar(
                    item['title'], '-') + ".mp4"
                filePath = os.path.abspath(filePath)
                if os.access(filePath, 0):
                    os.remove(filePath)

                videoID = item['id']
                resolutionList, urlList = self.tool.getVideoResolutionList(
                    videoID)
                if urlList is None:
                    printErr(14, item['title'] + '(' + self.tool.errmsg + ')')
                else:
                    selectIndex = self.__getVideoResolutionIndex(
                        resolutionList)
                    if self.ffmpeg.mergerByM3u8_Multithreading(
                            urlList[selectIndex], filePath,
                            showprogress=False):
                        printSUCCESS(14, item['title'])
                    else:
                        printErr(14,
                                 item['title'] + "(Download Or Merger Err!)")
        return
def changeSettings():
    global LANG

    Printf.settings(CONF)
    choice = Printf.enter(LANG.CHANGE_START_SETTINGS)
    if choice == '0':
        return

    while True:
        choice = Printf.enter(LANG.CHANGE_DOWNLOAD_PATH)
        if choice == '0':
            choice = CONF.downloadPath
        elif not os.path.isdir(choice):
            if not mkdirs(choice):
                Printf.err(LANG.MSG_PATH_ERR)
                continue
        CONF.downloadPath = choice
        break
    while True:
        choice = Printf.enter(LANG.CHANGE_AUDIO_QUALITY)
        if choice != '1' and choice != '2' and choice != '3' and choice != '0':
            Printf.err(LANG.MSG_INPUT_ERR)
            continue
        if choice == '0':
            CONF.audioQuality = AudioQuality.Normal
        if choice == '1':
            CONF.audioQuality = AudioQuality.High
        if choice == '2':
            CONF.audioQuality = AudioQuality.HiFi
        if choice == '3':
            CONF.audioQuality = AudioQuality.Master
        break
    while True:
        choice = Printf.enter(LANG.CHANGE_VIDEO_QUALITY)
        if choice != '1' and choice != '2' and choice != '3' and choice != '0':
            Printf.err(LANG.MSG_INPUT_ERR)
            continue
        if choice == '0':
            CONF.videoQuality = VideoQuality.P1080
        if choice == '1':
            CONF.videoQuality = VideoQuality.P720
        if choice == '2':
            CONF.videoQuality = VideoQuality.P480
        if choice == '3':
            CONF.videoQuality = VideoQuality.P360
        break
    CONF.onlyM4a = Printf.enter(LANG.CHANGE_ONLYM4A) == '1'
    # CONF.addExplicitTag = Printf.enter(LANG.CHANGE_ADD_EXPLICIT_TAG) == '1'
    # CONF.addHyphen = Printf.enter(LANG.CHANGE_ADD_HYPHEN) == '1'
    # CONF.addYear = Printf.enter(LANG.CHANGE_ADD_YEAR) == '1'
    # CONF.useTrackNumber = Printf.enter(LANG.CHANGE_USE_TRACK_NUM) == '1'
    CONF.checkExist = Printf.enter(LANG.CHANGE_CHECK_EXIST) == '1'
    # CONF.artistBeforeTitle = Printf.enter(LANG.CHANGE_ARTIST_BEFORE_TITLE) == '1'
    CONF.includeEP = Printf.enter(LANG.CHANGE_INCLUDE_EP) == '1'
    # CONF.addAlbumIDBeforeFolder = Printf.enter(LANG.CHANGE_ALBUMID_BEFORE_FOLDER) == '1'
    CONF.saveCovers = Printf.enter(LANG.CHANGE_SAVE_COVERS) == '1'
    CONF.showProgress = Printf.enter(LANG.CHANGE_SHOW_PROGRESS) == '1'
    CONF.language = Printf.enter(
        LANG.CHANGE_LANGUAGE +
        "('0'-English,'1'-中文,'2'-Turkish,'3'-Italiano,'4'-Czech,'5'-Arabic,'6'-Russian,'7'-Filipino,'8'-Croatian,'9'-Spanish,'10'-Portuguese,'11'-Ukrainian,'12'-Vietnamese,'13'-French,'14'-German):"
    )
    albumFolderFormat = Printf.enter(LANG.CHANGE_ALBUM_FOLDER_FORMAT)
    if albumFolderFormat == '0':
        albumFolderFormat = CONF.albumFolderFormat
    else:
        CONF.albumFolderFormat = albumFolderFormat
    trackFileFormat = Printf.enter(LANG.CHANGE_TRACK_FILE_FORMAT)
    if trackFileFormat == '0':
        trackFileFormat = CONF.trackFileFormat
    else:
        CONF.trackFileFormat = trackFileFormat

    LANG = setLang(CONF.language)
    Settings.save(CONF)
Ejemplo n.º 8
0
def setting():
    cf = TidalConfig()
    print("----------------Setting----------------")
    print("OutputDir    :\t" + cf.outputdir)
    print("SoundQuality :\t" + cf.quality)
    print("Resolution   :\t" + cf.resolution)
    print("ThreadNum    :\t" + cf.threadnum)
    while True:
        outputdir = myinput("Outputdir(Enter '0' Unchanged):".ljust(12))
        if outputdir == '0':
            outputdir = cf.outputdir
            break
        if os.path.isdir(outputdir) == False:
            printErr(0, "Path is Err!")
            continue
        break
    while True:
        index = myinputInt("Quality(0-LOW,1-HIGH,2-LOSSLESS):".ljust(12), 999)
        if index > 2 or index < 0:
            printErr(0, "Quality Err!")
            continue
        if index == 0:
            quality = 'LOW'
        if index == 1:
            quality = 'HIGH'
        if index == 2:
            quality = 'LOSSLESS'
        break
    while True:
        index = myinputInt(
            "Resolution(0-1080,1-720,2-480,3-360,4-240):".ljust(12), 99)
        if index > 4 or index < 0:
            printErr(0, "ThreadNum Err")
            continue
        if index == 0:
            resolution = '1080'
        if index == 1:
            resolution = '720'
        if index == 2:
            resolution = '480'
        if index == 3:
            resolution = '360'
        if index == 4:
            resolution = '240'
        break
    while True:
        threadnum = myinput("ThreadNum:".ljust(12))
        if cf.valid_threadnum(threadnum) == False:
            printErr(0, "ThreadNum Err")
            continue
        break

    cf.set_outputdir(outputdir)
    cf.set_quality(quality)
    cf.set_resolution(resolution)
    cf.set_threadnum(threadnum)

    pathHelper.mkdirs(outputdir + "/Album/")
    pathHelper.mkdirs(outputdir + "/Playlist/")
    pathHelper.mkdirs(outputdir + "/Video/")
    pathHelper.mkdirs(outputdir + "/Favorite/")
    return
Ejemplo n.º 9
0
    def downloadPlaylist(self, playlist_id=None):
        while True:
            targetDir = self.config.outputdir + "/Playlist/"
            if playlist_id is None:
                print("--------------PLAYLIST-----------------")
                sID = printChoice("Enter PlayListID(Enter '0' go back):")
                if sID == '0':
                    return
            else:
                sID = playlist_id

            aPlaylistInfo, aItemInfo = self.tool.getPlaylist(sID)
            if self.tool.errmsg != "":
                printErr(0, "Get PlaylistInfo Err! " + self.tool.errmsg)
                return

            print("[Title]                %s" % (aPlaylistInfo['title']))
            print("[Type]                 %s" % (aPlaylistInfo['type']))
            print("[NumberOfTracks]       %s" %
                  (aPlaylistInfo['numberOfTracks']))
            print("[NumberOfVideos]       %s" %
                  (aPlaylistInfo['numberOfVideos']))
            print("[Duration]             %s\n" % (aPlaylistInfo['duration']))

            # Creat OutputDir
            targetDir = targetDir + pathHelper.replaceLimitChar(
                aPlaylistInfo['title'], '-')
            targetDir = os.path.abspath(targetDir).strip()
            pathHelper.mkdirs(targetDir)
            # write msg
            string = self.tool.convertPlaylistInfoToString(
                aPlaylistInfo, aItemInfo)
            with codecs.open(targetDir + "/PlaylistInfo.txt", 'w',
                             'utf-8') as fd:
                fd.write(string)
            # download cover
            coverPath = targetDir + '/' + pathHelper.replaceLimitChar(
                aPlaylistInfo['title'], '-') + '.jpg'
            coverUrl = self.tool.getPlaylistArtworkUrl(aPlaylistInfo['uuid'])
            check = netHelper.downloadFile(coverUrl, coverPath)

            # download track
            bBreakFlag = False
            bFirstTime = True
            errIndex = []
            index = 0

            while bBreakFlag is False:
                self.check.clear()
                index = 0
                tmpcoverpath = []
                for item in aItemInfo:
                    type = item['type']
                    item = item['item']
                    if type != 'track':
                        continue

                    index = index + 1
                    if bFirstTime is False:
                        if self.check.isInErr(index - 1, errIndex) == False:
                            continue

                    streamInfo = self.tool.getStreamUrl(
                        str(item['id']), self.config.quality)
                    # streamInfo = self.tool.getStreamUrl(str(item['id']), 'DOLBY_ATMOS')
                    if self.tool.errmsg != "" or not streamInfo:
                        printErr(
                            14, item['title'] + "(Get Stream Url Err!!" +
                            self.tool.errmsg + ")")
                        continue
                    aAlbumInfo = self.tool.getAlbum(item['album']['id'])
                    fileType = self._getSongExtension(streamInfo['url'])

                    # change targetDir
                    targetDir2 = targetDir
                    if self.config.plfile2arfolder == "True":
                        targetDir2 = self.__creatAlbumDir(aAlbumInfo)
                        filePath = self.__getAlbumSongSavePath(
                            targetDir2, aAlbumInfo, item, fileType)
                        paraList = {
                            'album': aAlbumInfo,
                            'title': item['title'],
                            'trackinfo': item,
                            'url': streamInfo['url'],
                            'path': filePath,
                            'retry': 3,
                            'key': streamInfo['encryptionKey']
                        }
                    else:
                        seq = self.tool.getIndexStr(index, len(aItemInfo))
                        filePath = targetDir2 + '/' + seq + " " + pathHelper.replaceLimitChar(
                            item['title'], '-') + fileType
                        paraList = {
                            'album': aAlbumInfo,
                            'index': index,
                            'title': item['title'],
                            'trackinfo': item,
                            'url': streamInfo['url'],
                            'path': filePath,
                            'retry': 3,
                            'key': streamInfo['encryptionKey']
                        }

                    try:
                        coverPath = targetDir2 + '/' + pathHelper.replaceLimitChar(
                            aAlbumInfo['title'], '-') + '.jpg'
                        coverUrl = self.tool.getAlbumArtworkUrl(
                            aAlbumInfo['cover'])
                        netHelper.downloadFile(coverUrl, coverPath)
                        paraList['coverpath'] = coverPath
                        tmpcoverpath.append(coverPath)
                    except:
                        cmdHelper.myprint(
                            "Could not download artwork for '{}'".format(
                                item['title']), cmdHelper.TextColor.Red, None)

                    if self.config.onlym4a == "True":
                        self.check.addPath(filePath.replace(".mp4", ".m4a"))
                    else:
                        self.check.addPath(filePath)
                    self.thread.start(self.__thradfunc_dl, paraList)
                self.thread.waitAll()
                self.tool.removeTmpFile(targetDir)

                # remove cover
                if self.config.savephoto != 'True':
                    for item in tmpcoverpath:
                        pathHelper.remove(item)

                bBreakFlag = True
                bFirstTime = False

                # check
                isErr, errIndex = self.check.checkPaths()
                if isErr:
                    check = printChoice(
                        "[Err]\t\t" + str(len(errIndex)) +
                        " Tracks Download Failed.Try Again?(y/n):")
                    if check == 'y' or check == 'Y':
                        bBreakFlag = False

            # download video
            for item in aItemInfo:
                type = item['type']
                item = item['item']
                if type != 'video':
                    continue

                filePath = targetDir + '/' + pathHelper.replaceLimitChar(
                    item['title'], '-') + ".mp4"
                filePath = os.path.abspath(filePath)
                if os.access(filePath, 0):
                    os.remove(filePath)

                videoID = item['id']
                resolutionList, urlList = self.tool.getVideoResolutionList(
                    videoID)
                if urlList is None:
                    printErr(14, item['title'] + '(' + self.tool.errmsg + ')')
                else:
                    selectIndex = self.__getVideoResolutionIndex(
                        resolutionList)
                    if self.ffmpeg.mergerByM3u8_Multithreading2(
                            urlList[int(selectIndex)],
                            filePath,
                            showprogress=self.showpro):
                        printSUCCESS(14, item['title'])
                    else:
                        printErr(14,
                                 item['title'] + "(Download Or Merger Err!)")
            if playlist_id is not None:
                return
        return
Ejemplo n.º 10
0
def setting():
    cf = TidalConfig()
    print("----------------Settings----------------")
    print("Output directory                 :\t" + cf.outputdir)
    print("Sound Quality                    :\t" + cf.quality)
    print("Video Resolution                 :\t" + cf.resolution)
    print("Download Threads                 :\t" + cf.threadnum)
    print("Only M4a                         :\t" + cf.onlym4a)
    print("Show download progress           :\t" + cf.showprogress +
          "(enable when threadnum=1)")
    print("Use hyphens                      :\t" + cf.addhyphen +
          "(between number and title)")
    print("Add year                         :\t" + cf.addyear +
          "(in album title)")
    print("Add explicit tag                 :\t" + cf.addexplicit)
    print("Playlist songs in artist folders :\t" + cf.plfile2arfolder +
          "(organized with artist folder)")
    print("Include singles                  :\t" + cf.includesingle +
          "(download artist album)")
    print("Save covers                      :\t" + cf.savephoto)
    print("ArtistName Before Track-Title    :\t" + cf.artistbeforetitle)
    print("Add ID Before AlbumFolderName    :\t" + cf.addAlbumidbeforefolder)
    while True:
        outputdir = myinput("Output directory(Enter '0' Unchanged):".ljust(12))
        if outputdir == '0':
            outputdir = cf.outputdir
            break
        if os.path.isdir(outputdir) == False:
            printErr(0, "Path is Err!")
            continue
        break
    while True:
        index = myinputInt(
            "Download Quality(0-LOW,1-HIGH,2-LOSSLESS,3-HI_RES):".ljust(12),
            999)
        if index > 3 or index < 0:
            printErr(0, "Quality Err!")
            continue
        if index == 0:
            quality = 'LOW'
        if index == 1:
            quality = 'HIGH'
        if index == 2:
            quality = 'LOSSLESS'
        if index == 3:
            quality = 'HI_RES'
        break
    while True:
        index = myinputInt(
            "Video resolution(0-1080,1-720,2-480,3-360,4-240):".ljust(12), 99)
        if index > 4 or index < 0:
            printErr(0, "Resolution Err")
            continue
        if index == 0:
            resolution = '1080'
        if index == 1:
            resolution = '720'
        if index == 2:
            resolution = '480'
        if index == 3:
            resolution = '360'
        if index == 4:
            resolution = '240'
        break
    while True:
        threadnum = myinput("Number of download threads:".ljust(12))
        if cf.valid_threadnum(threadnum) == False:
            printErr(0, "ThreadNum Err")
            continue
        break

    status = myinputInt("Convert Mp4 to M4a(0-No, 1-Yes):".ljust(12), 0)
    status2 = myinputInt(
        "Show download progress (only available on single thread)(0-No, 1-Yes):"
        .ljust(12), 0)
    status3 = myinputInt(
        "Use hyphens instead of spaces in file names(0-No, 1-Yes):".ljust(12),
        0)

    while True:
        index = myinputInt(
            "Add year to album folder names(0-No, 1-Before, 2-After):".ljust(
                12), 99)
        if index > 2 or index < 0:
            printErr(0, "Addyear input Err")
            continue
        if index == 0:
            addyear = 'No'
        if index == 1:
            addyear = 'Before'
        if index == 2:
            addyear = 'After'
        break

    status5 = myinputInt(
        "Download playlist songs in artist folder structure? (0-No,1-Yes):".
        ljust(12), 0)
    status6 = myinputInt(
        "Add explicit tag to file names(0-No, 1-Yes):".ljust(12), 0)
    status7 = myinputInt(
        "Include singles and EPs when downloading an artist's albums (0-No, 1-Yes):"
        .ljust(12), 0)
    status8 = myinputInt("Save covers(0-No, 1-Yes):".ljust(12), 0)
    status9 = myinputInt(
        "Add artistName before trackTitle(0-No, 1-Yes):".ljust(12), 0)
    status10 = myinputInt(
        "Add ID Before AlbumFolderName(0-No, 1-Yes):".ljust(12), 0)

    cf.set_outputdir(outputdir)
    cf.set_quality(quality)
    cf.set_resolution(resolution)
    cf.set_threadnum(threadnum)
    cf.set_onlym4a(status)
    cf.set_showprogress(status2)
    cf.set_addhyphen(status3)
    cf.set_addyear(addyear)
    cf.set_plfile2arfolder(status5)
    cf.set_addexplicit(status6)
    cf.set_includesingle(status7)
    cf.set_savephoto(status8)
    cf.set_artistbeforetitle(status9)
    cf.set_addAlbumidbeforefolder(status10)

    pathHelper.mkdirs(outputdir + "/Album/")
    pathHelper.mkdirs(outputdir + "/Playlist/")
    pathHelper.mkdirs(outputdir + "/Video/")
    pathHelper.mkdirs(outputdir + "/Favorite/")
    return