# -*- coding: utf-8 -*-
from setuptools import setup

packages = \
['scripts', 'xklb']

package_data = \
{'': ['*']}

install_requires = \
['catt',
 'ffmpeg-python',
 'humanize',
 'ipython',
 'joblib',
 'mutagen',
 'natsort',
 'protobuf<4',
 'pysubs2>=1.4.3,<2.0.0',
 'python-mpv-jsonipc>=1.1.13,<2.0.0',
 'rich',
 'sqlite-utils',
 'subliminal',
 'tabulate',
 'tinytag']

entry_points = \
{'console_scripts': ['lb = xklb.lb:main', 'library = xklb.lb:main']}

setup_kwargs = {
    'name': 'xklb',
    'version': '1.16.17',
    'description': 'xk library',
    'long_description': '# lb: xk media library\n\nA wise philosopher once told me, "[The future is autotainment](https://www.youtube.com/watch?v=F9sZFrsjPp0)".\n\nManage large media libraries. Similar to Plex but more minimalist.\nPrimary usage is local filesystem but also supports some virtual constructs like\ntracking video playlists (eg. YouTube subscriptions) or daily browser tabs.\n\nRequired: `ffmpeg`\n\nRecommended: `mpv`, `fish`, `firefox`\n\n## Install\n\nLinux recommended but [Windows setup instructions](./Windows.md) available.\n\n    pip install xklb\n\n    $ library\n    xk media library [lb]\n\n    local media subcommands:\n      fsadd [extract, xr]          Create a local media database; Add folders\n      subtitle [sub]               Find subtitles for local media\n      listen [lt]                  Listen to local media\n      watch [wt]                   Watch local media\n      read [books, docs]           Read books\n      filesystem [fs]              Browse files\n      bigdirs [largefolders]       View folders which take up much room\n      dedupe                       Deduplicate audio files\n\n    online media subcommands:\n      tubeadd [ta, xt]             Create a tube database; Add playlists\n      tubeupdate [tu]              Get new videos from saved playlists\n      tubelist [playlists]         List added playlists\n      tubewatch [tw, entries]      Watch the tube\n      tubelisten [tl]              Listen to the tube\n\n    playback subcommands:\n      now                          Print what is currently playing\n      next                         Play next file\n      stop                         Stop all playback\n\n    browser tab subcommands:\n      tabsadd                      Create a tabs database; Add URLs\n      tabs [tabswatch, tb]         Open your tabs for the day\n    \n\n## Quick Start -- watch online media on your PC\n\n    wget https://github.com/chapmanjacobd/lb/raw/main/examples/mealtime.tw.db\n    library tubewatch mealtime.tw.db\n\n## Quick Start -- listen to online media on a chromecast group\n\n    wget https://github.com/chapmanjacobd/lb/raw/main/examples/music.tl.db\n    library tubelisten music.tl.db -ct "House speakers"\n\n## Start -- local media\n\n### 1. Extract Metadata\n\nFor thirty terabytes of video the initial scan takes about four hours to complete.\nAfter that, subsequent scans of the path (or any subpaths) are much quicker--only\nnew files will be read by `ffprobe`.\n\n    library fsadd tv.db ./video/folder/\n\n![termtosvg](./examples/extract.svg)\n\n### 2. Watch / Listen from local files\n\n    library wt tv.db                          # the default post-action is to do nothing\n    library wt tv.db --post-action delete     # delete file after playing\n    library lt finalists.db --post-action=ask # ask whether to delete after playing\n\nTo stop playing press Ctrl+C in either the terminal or mpv\n\n## Start -- online media\n\n### 1. Download Metadata\n\nDownload playlist and channel metadata. Break free of the YouTube algo~\n\n    library tubeadd educational.db https://www.youtube.com/c/BranchEducation/videos\n\n[![termtosvg](./examples/tubeadd.svg "library tubeadd example")](https://asciinema.org/a/BzplqNj9sCERH3A80GVvwsTTT)\n\nAnd you can always add more later--even from different websites.\n\n    library tubeadd maker.db https://vimeo.com/terburg\n\nTo prevent mistakes the default configuration is to download metadata for only\nthe most recent 20,000 videos per playlist/channel.\n\n    library tubeadd maker.db --yt-dlp-config playlistend=1000\n\nBe aware that there are some YouTube Channels which have many items--for example\nthe TEDx channel has about 180,000 videos. Some channels even have upwards of\ntwo million videos. More than you could likely watch in one sitting.\nOn a high-speed connection (>500 Mbps), it can take up to five hours to download\nthe metadata for 180,000 videos.\n\n#### 1a. Get new videos for saved playlists\n\nTubeupdate will go through the list of added playlists and fetch metadata for\nany videos not previously seen.\n\n    library tubeupdate\n\n### 2. Watch / Listen from websites\n\n    library tubewatch maker.db\n\nTo stop playing press Ctrl+C in either the terminal or mpv\n\n## Start -- tabs (visit websites on a schedule)\n\ntabs is a way to organize your visits to URLs that you want to visit every once in a while.\n\nIf you want to track _changes_ to websites over time there are better tools out there, like\n`huginn`, `urlwatch`, or `changedetection.io`.\n\nThe use-case of tabs are websites that you know are going to change: subreddits, games,\nor tools that you want to use for a few minutes daily, weekly, monthly, quarterly, or yearly.\n\n### 1. Add your websites\n\n    library tabsadd --frequency monthly --category fun https://old.reddit.com/r/Showerthoughts/top/?sort=top&t=month https://old.reddit.com/r/RedditDayOf/top/?sort=top&t=month\n\n### 2. Add library tabs to cron\n\nlibrary tabs is meant to run **once per day**. Here is how you would configure it with `crontab`:\n\n    45 9 * * * DISPLAY=:0 library tabs /home/my/tabs.db\n\nOr with `systemd`:\n\n    ~/.config/systemd/user/tabs.service\n    [Unit]\n    Description=xklb daily browser tabs\n\n    [Service]\n    Environment="DISPLAY=:0"\n    ExecStart="library" "tabs" "/home/xk/lb/tabs.db"\n    RemainAfterExit=no\n\n    ~/.config/systemd/user/tabs.timer\n    [Unit]\n    Description=xklb daily browser tabs\n\n    [Timer]\n    Persistent=yes\n    OnCalendar=*-*-* 9:58\n    RemainAfterElapse=yes\n\n    systemctl --user daemon-reload\n    systemctl --user enable --now tabs.service\n\nYou can also invoke tabs manually:\n\n    library tabs -L 1  # open one tab\n\n## Things to know.db\n\nWhen the database file path is not specified, `video.db` will be created / used.\n\n    library fsadd ./tv/\n\nThe same for audio: `audio.db` will be created / used.\n\n    library fsadd --audio ./music/\n\nLikewise, `fs.db` from:\n\n    library fsadd --filesystem /any/path/\n\nIf you want to specify more than one directory you need to mention the db file explicitly.\n\n    library fsadd --filesystem one/\n    library fsadd --filesystem fs.db one/ two/\n\nOrganize via separate databases.\n\n    library fsadd --audio both.db ./audiobooks/ ./podcasts/\n    library fsadd --audio audiobooks.db ./audiobooks/\n    library fsadd --audio podcasts.db ./podcasts/ ./another/more/secret/podcasts_folder/\n\n## Usage\n\n    $ library watch -h\n    usage: library watch [database] [optional args]\n\n    Control playback:\n        To stop playback press Ctrl-C in either the terminal or mpv\n\n        Create global shortcuts in your desktop environment by sending commands to mpv_socket:\n        echo \'playlist-next force\' | socat - /tmp/mpv_socket\n\n    If not specified, watch will try to read video.db in the working directory:\n        library watch\n        library watch ./my/other/database/is-a/db.db\n\n    Override the default player (mpv):\n        library does a lot of things to try to automatically use your preferred media player\n        but if it doesn\'t guess right you can make it explicit:\n        library watch --player "vlc --vlc-opts"\n\n    Cast to chromecast groups:\n        library watch --cast --cast-to "Office pair"\n        library watch -ct "Office pair"  # equivalent\n        If you don\'t know the exact name of your chromecast group run `catt scan`\n\n    Print instead of play:\n        library watch --print --limit 10  # print the next 10 files\n        library watch -p -L 10  # print the next 10 files\n        library watch -p  # this will print _all_ the media. be cautious about `-p` on an unfiltered set\n\n        Printing modes\n        library watch -p    # print in a table\n        library watch -p p  # equivalent\n        library watch -p a  # print an aggregate report\n        library watch -p f  # print fields -- useful for piping paths to utilities like xargs or GNU Parallel\n\n        Check if you have downloaded something before\n        library watch -u duration -p -s \'title\'\n\n        Print an aggregate report of deleted media\n        library watch -w is_deleted=1 -p=a\n        ╒═══════════╤══════════════╤═════════╤═════════╕\n        │ path      │ duration     │ size    │   count │\n        ╞═══════════╪══════════════╪═════════╪═════════╡\n        │ Aggregate │ 14 days, 23  │ 50.6 GB │   29058 │\n        │           │ hours and 42 │         │         │\n        │           │ minutes      │         │         │\n        ╘═══════════╧══════════════╧═════════╧═════════╛\n        Total duration: 14 days, 23 hours and 42 minutes\n\n        Print an aggregate report of media that has no duration information (likely corrupt media)\n        library watch -w \'duration is null\' -p=a\n\n        Print a list of filenames which have below 1280px resolution\n        library wt -w \'width<1280\' -p=f\n\n        Print media you have partially viewed with mpv\n        library watch -p=v\n\n        View how much time you have watched\n        library watch -w play_count\'>\'0 -p=a\n\n        See how much video you have\n        library wt video.db -p=a\n        ╒═══════════╤═════════╤═════════╤═════════╕\n        │ path      │   hours │ size    │   count │\n        ╞═══════════╪═════════╪═════════╪═════════╡\n        │ Aggregate │  145769 │ 37.6 TB │  439939 │\n        ╘═══════════╧═════════╧═════════╧═════════╛\n        Total duration: 16 years, 7 months, 19 days, 17 hours and 25 minutes\n\n        View all the columns\n        library watch -p -L 1 --cols \'*\'\n\n        Open ipython with all of your media\n        library watch -vv -p --cols \'*\'\n        ipdb> len(db_resp)\n        462219\n\n    Set the play queue size:\n        By default the play queue is 120--long enough that you likely have not noticed\n        but short enough that the program is snappy.\n\n        If you want everything in your play queue you can use the aid of infinity.\n        Pick your poison (these all do effectively the same thing):\n        library watch -L inf\n        library watch -l inf\n        library watch --queue inf\n        library watch -L 99999999999999999999999\n\n        You may also want to restrict the play queue.\n        For example, when you only want 1000 random files:\n        library watch -u random -L 1000\n\n    Offset the play queue:\n        You can also offset the queue. For example if you want to skip one or ten media:\n        library watch -S 10  # offset ten from the top of an ordered query\n\n    Repeat\n        library watch                  # listen to 120 random songs (DEFAULT_PLAY_QUEUE)\n        library watch --limit 5        # listen to FIVE songs\n        library watch -l inf -u random # listen to random songs indefinitely\n        library watch -s infinite      # listen to songs from the band infinite\n\n    Constrain media by search:\n        Audio files have many tags to readily search through so metadata like artist,\n        album, and even mood are included in search.\n        Video files have less consistent metadata and so only paths are included in search.\n        library watch --include happy  # only matches will be included\n        library watch -s happy         # equivalent\n        library watch --exclude sad    # matches will be excluded\n        library watch -E sad           # equivalent\n\n        Search only the path column\n        library watch -O -s \'path : mad max\'\n        library watch -O -s \'path : "mad max"\' # add "quotes" to be more strict\n\n        Double spaces are parsed as one space\n        -s \'  ost\'        # will match OST and not ghost\n        -s toy story      # will match \'/folder/toy/something/story.mp3\'\n        -s \'toy  story\'   # will match more strictly \'/folder/toy story.mp3\'\n\n    Constrain media by arbitrary SQL expressions:\n        library watch --where audio_count = 2  # media which have two audio tracks\n        library watch -w "language = \'eng\'"    # media which have an English language tag\n                                                    (this could be audio _or_ subtitle)\n        library watch -w subtitle_count=0      # media that doesn\'t have subtitles\n\n    Constrain media to duration (in minutes):\n        library watch --duration 20\n        library watch -d 6  # 6 mins ±10 percent (ie. between 5 and 7 mins)\n        library watch -d-6  # less than 6 mins\n        library watch -d+6  # more than 6 mins\n\n        Duration can be specified multiple times:\n        library watch -d+5 -d-7  # should be similar to -d 6\n\n        If you want exact time use `where`\n        library watch --where \'duration=6*60\'\n\n    Constrain media to file size (in megabytes):\n        library watch --size 20\n        library watch -z 6  # 6 MB ±10 percent (ie. between 5 and 7 MB)\n        library watch -z-6  # less than 6 MB\n        library watch -z+6  # more than 6 MB\n\n    Constrain media by throughput:\n        Bitrate information is not explicitly saved.\n        You can use file size and duration as a proxy for throughput:\n        library watch -w \'size/duration<50000\'\n\n    Constrain media to portrait orientation video:\n        library watch --portrait\n        library watch -w \'width<height\' # equivalent\n\n    Specify media play order:\n        library watch --sort duration   # play shortest media first\n        library watch -u duration desc  # play longest media first\n        You can use multiple SQL ORDER BY expressions\n        library watch -u subtitle_count > 0 desc # play media that has at least one subtitle first\n\n    Play media in order (similarly named episodes):\n        library watch --play-in-order\n        There are multiple strictness levels of --play-in-order.\n        If things aren\'t playing in order try adding more `O`s:\n        library watch -O    # normal\n        library watch -OO   # slower, more complex algorithm\n        library watch -OOO  # strict\n\n    Post-actions -- choose what to do after playing:\n        library watch --post-action delete  # delete file after playing\n        library watch -k ask  # ask after each whether to keep or delete\n\n        library watch -k askkeep  # ask after each whether to move to a keep folder or delete\n        The default location of the keep folder is ./keep/ (relative to the played media file)\n        You can change this by explicitly setting an *absolute* `keep-dir` path:\n        library watch -k askkeep --keep-dir /home/my/music/keep/\n\n    Experimental options:\n        Duration to play (in seconds) while changing the channel\n        library watch --interdimensional-cable 40\n        library watch -4dtv 40\n\n\n### You can pipe stuff\n\n#### [lowcharts](https://github.com/juan-leon/lowcharts)\n\n    $ wt-dev -p f -col time_created | lowcharts timehist -w 80\n    Matches: 445183.\n    Each ∎ represents a count of 1896\n    [2022-04-13 03:16:05] [151689] ∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎\n    [2022-04-19 07:59:37] [ 16093] ∎∎∎∎∎∎∎∎\n    [2022-04-25 12:43:09] [ 12019] ∎∎∎∎∎∎\n    [2022-05-01 17:26:41] [ 48817] ∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎\n    [2022-05-07 22:10:14] [ 36259] ∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎\n    [2022-05-14 02:53:46] [  3942] ∎∎\n    [2022-05-20 07:37:18] [  2371] ∎\n    [2022-05-26 12:20:50] [   517]\n    [2022-06-01 17:04:23] [  4845] ∎∎\n    [2022-06-07 21:47:55] [  2340] ∎\n    [2022-06-14 02:31:27] [   563]\n    [2022-06-20 07:14:59] [ 13836] ∎∎∎∎∎∎∎\n    [2022-06-26 11:58:32] [  1905] ∎\n    [2022-07-02 16:42:04] [  1269]\n    [2022-07-08 21:25:36] [  3062] ∎\n    [2022-07-15 02:09:08] [  9192] ∎∎∎∎\n    [2022-07-21 06:52:41] [ 11955] ∎∎∎∎∎∎\n    [2022-07-27 11:36:13] [ 50938] ∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎\n    [2022-08-02 16:19:45] [ 70973] ∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎\n    [2022-08-08 21:03:17] [  2598] ∎\n\n![video width](https://user-images.githubusercontent.com/7908073/184737808-b96fbe65-a1d9-43c2-b6b4-4bdfab592190.png)\n\n![fps](https://user-images.githubusercontent.com/7908073/184738438-ee566a4b-2da0-4e6d-a4b3-9bfca036aa2a.png)\n\n#### rsync\n\nI use rsync to move files instead of copy-on-write duplication because I want deletions to stick.\nWhen I press the next button in the car I delete the song from my curated universe.\n\n    function mrmusic\n        rsync -a --remove-source-files --files-from=(\n            library lt ~/lb/audio.db -s /mnt/d/80_Now_Listening/ -p f             --moved /mnt/d/80_Now_Listening/ /mnt/d/ | psub\n        ) /mnt/d/80_Now_Listening/ /mnt/d/\n\n        rsync -a --remove-source-files --files-from=(\n            library lt ~/lb/audio.db -w play_count=0 -u random -L 1200 -p f             --moved /mnt/d/ /mnt/d/80_Now_Listening/ | psub\n        ) /mnt/d/ /mnt/d/80_Now_Listening/\n    end\n\n#### Datasette\n\nExplore `library` databases in your browser\n\n    pip install datasette\n    datasette tv.db\n\n### TODOs (PRs welcome)\n\n- test windows: now, next, stop\n- fs: photos\n- tube: remember passed in yt-dlp arguments per playlist for tube-update\n- tube: make sure playlistless media doesn\'t save to the playlists table\n- tube: basic tests\n- all: more test coverage -- https://hypothesis.readthedocs.io/en/latest/quickstart.html\n- all: follow yt-dlp print arg syntax\n- all: follow fd-find size arg syntax\n- fs: split_by_silence without modifying files\n\n',
    'author': 'Jacob Chapman',
    'author_email': '7908073+chapmanjacobd@users.noreply.github.com',
    'maintainer': 'None',
    'maintainer_email': 'None',
    'url': 'https://github.com/chapmanjacobd/lb/',
    'packages': packages,
    'package_data': package_data,
    'install_requires': install_requires,
    'entry_points': entry_points,
    'python_requires': '>=3.8,<4.0',
}


setup(**setup_kwargs)
