[
  {
    "path": ".appveyor.yml",
    "content": "\n#---------------------------------#\n#      general configuration      #\n#---------------------------------#\n\n# version format\nversion: 1.0.{build}-{branch}\n\n# branches to build\nbranches:\n  # blacklist\n  except:\n    - gh-pages\n\n# Skipping commits affecting specific files (GitHub only). More details here: /docs/appveyor-yml\nskip_commits:\n  # Default `skip` messages are applied even on tag builds with APPVEYOR_IGNORE_COMMIT_FILTERING_ON_TAG==true\n  message: /\\[_skip ci_\\]|\\[_ci skip_\\]|\\[_skip_ci_\\]|\\[_ci_skip_\\]/\n  files:\n    - README.md\n    - THIRD_PARTY_NOTICES.md\n#    - docs/*\n#    - '**/*.png'\n#    - '**/*.jpg'\n#    - '**/*.jpeg'\n#    - '**/*.bmp'\n#    - '**/*.gif'\n#    - '**/*.js'\n#    - '**/*.txt'\n#    - '**/*.md'\n\n# Maximum number of concurrent jobs for the project\nmax_jobs: 1\n\n#---------------------------------#\n#    environment configuration    #\n#---------------------------------#\n\n# Build worker image (VM template)\nimage: Visual Studio 2019\n\n# environment variables\nenvironment:\n  APPVEYOR_IGNORE_COMMIT_FILTERING_ON_TAG: true\n  git_user_email: qwertiest@mail.ru\n  git_user_name: TheQwertiest\n  GITHUB_TOKEN:\n    secure: gBfHQnRcGcTS0yQXWOHhKfDkTZfIBwPIDjTsCQOGmOSPkRqs1QPYBX47BjCvJKim\n\n# this is how to allow failing jobs in the matrix\nmatrix:\n  fast_finish: true     # set this flag to immediately finish build once one of the jobs fails.\n\ncache:\n  - workspaces\\packages -> **\\packages.config\n  - c:\\tools\\vcpkg\\installed\n\n# scripts that run after cloning repository\ninstall:\n  #  vcpkg\n  - cd C:\\Tools\\vcpkg\n  - git pull\n  - .\\bootstrap-vcpkg.bat\n  - cd %APPVEYOR_BUILD_FOLDER%\n  - vcpkg remove --outdated --recurse\n  - cmd: set VCPKG_PLATFORM_TOOLSET=v142\n  - vcpkg install cpprestsdk:x86-windows-static\n  - vcpkg integrate install\n  # GitHub CLI\n  - choco install gh -y\n  - refreshenv\n  - gh config set -h github.com git_protocol https\n  # PIP\n  - py -3 -m pip install semver\n  # Component\n  - py -u scripts\\setup.py\n\n#---------------------------------#\n#       build configuration       #\n#---------------------------------#\n\n# build platform, i.e. x86, x64, Any CPU. This setting is optional.\nplatform:\n  - Win32\n\n# build Configuration, i.e. Debug, Release, etc.\nconfiguration:\n  - Debug\n  - Release\n\n# Build settings, not to be confused with \"before_build\" and \"after_build\".\n# \"project\" is relative to the original build directory and not influenced by directory changes in \"before_build\".\nbuild:\n  parallel: true                  # enable MSBuild parallel builds\n  project: workspaces\\foo_spotify.sln      # path to Visual Studio solution or project\n\n  # MSBuild verbosity level\n  verbosity: normal\n\n# scripts to run before build\nbefore_build:\n  - nuget restore workspaces\\foo_spotify.sln\n\n# to run your custom scripts instead of automatic MSBuild\nbuild_script:\n\n# scripts to run after build (working directory and environment changes are persisted from the previous steps)\nafter_build:\n\n# scripts to run *after* solution is built and *before* automatic packaging occurs (web apps, NuGet packages, Azure Cloud Services)\nbefore_package:\n  - if '%configuration%' == 'Debug' (\n      py -u scripts\\pack_component.py --debug &&\n      ren \"_result\\%platform%_%configuration%\\foo_spotify.fb2k-component\" \"foo_spotify.fb2k-component_debug\"\n    )\n    else (\n      py -u scripts\\pack_component.py\n    )\n\n# to disable automatic builds\n#build: off\n\n#---------------------------------#\n#      artifacts configuration    #\n#---------------------------------#\n\nartifacts:\n  # pushing a single file with environment variable in path and \"Deployment name\" specified\n  - path: _result\\$(platform)_$(configuration)\\foo_spotify.fb2k-component\n    name: SPTF package (Release)\n  - path: _result\\$(platform)_$(configuration)\\foo_spotify_pdb.zip\n    name: SPTF PDB package (Release)\n  - path: _result\\$(platform)_$(configuration)\\foo_spotify.fb2k-component_debug\n    name: SPTF package (Debug)\n\n#---------------------------------#\n#     deployment configuration    #\n#---------------------------------#\n\n# providers: Local, FTP, WebDeploy, AzureCS, AzureBlob, S3, NuGet, Environment\n# provider names are case-sensitive!\ndeploy:\n  description: 'Dummy description'\n  provider: GitHub\n  auth_token: $(GITHUB_TOKEN)\n  artifact: /foo_spotify.*/           # upload all NuGet packages to release assets\n  prerelease: true\n  on:\n    branch: master                 # release from master branch only\n    appveyor_repo_tag: true        # deploy on tag push only\n\n\n# scripts to run before deployment\nbefore_deploy:\n\n# scripts to run after deployment\nafter_deploy:\n\n# to run your custom scripts instead of provider deployments\ndeploy_script:\n\n# to disable deployment\n# deploy: off\n\n#---------------------------------#\n#        global handlers          #\n#---------------------------------#\n\n# on successful build\non_success:\n  # issues clean up\n  - ps: |\n        If ($env:APPVEYOR_REPO_TAG -eq $true -and $env:CONFIGURATION -eq \"Release\")\n        {\n          py -u submodules\\fb2k_utils\\scripts\\close_gh_issues.py\n        }\n  # gh-pages\n  - ps: |\n        If ($env:APPVEYOR_REPO_TAG -eq $true -and $env:CONFIGURATION -eq \"Release\")\n        {\n          git config --global credential.helper store\n          Add-Content \"$env:USERPROFILE\\.git-credentials\" \"https://$($env:GITHUB_TOKEN):x-oauth-basic@github.com`n\"\n          git config --global user.email $env:git_user_email\n          git config --global user.name $env:git_user_name\n          git clone -q --depth=1 -b gh-pages https://github.com/$($env:APPVEYOR_REPO_NAME).git gh-pages\n          py -u scripts\\update_gh_pages.py\n          cd gh-pages\n          git add -A 2>&1\n          git commit -q -m \"Updated documentation: $env:APPVEYOR_REPO_TAG_NAME ($env:APPVEYOR_REPO_COMMIT)\"\n          git push -q origin gh-pages\n          cd $env:APPVEYOR_BUILD_FOLDER\n        }\n\n# on build failure\non_failure:\n\n# after build failure or success\non_finish:\n\n#---------------------------------#\n#         notifications           #\n#---------------------------------#\n\nnotifications:\n"
  },
  {
    "path": ".bandit",
    "content": "skips: ['B101','B404','B602','B607']\n"
  },
  {
    "path": ".codacy.yml",
    "content": "engines:\n  prospector:\n    enabled: true\n    python_version: 3\n  pylint:\n    enabled: true\n    python_version: 3\nexclude_paths:\n  - 'libspotify/**'\n  - 'submodules/**'"
  },
  {
    "path": ".gitattributes",
    "content": "# Auto detect text files and perform LF normalization\n* text=auto\n# Custom for Visual Studio\n*.cs     diff=csharp\n# Standard to msysgit\n*.doc\t diff=astextplain\n*.DOC\t diff=astextplain\n*.docx diff=astextplain\n*.DOCX diff=astextplain\n*.dot  diff=astextplain\n*.DOT  diff=astextplain\n*.pdf  diff=astextplain\n*.PDF\t diff=astextplain\n*.rtf\t diff=astextplain\n*.RTF\t diff=astextplain\n*.zip filter=lfs diff=lfs merge=lfs -text\n\nlibspotify/* linguist-detectable=false\nscripts/* linguist-detectable=false\n"
  },
  {
    "path": ".gitignore",
    "content": "# Created by https://www.gitignore.io/api/visualstudio\n\n### VisualStudio ###\n## Ignore Visual Studio temporary files, build results, and\n## files generated by popular Visual Studio add-ons.\n\n# User-specific files\n*.suo\n*.user\n*.userosscache\n*.sln.docstates\n\n# User-specific files (MonoDevelop/Xamarin Studio)\n*.userprefs\n\n# Build results\n/_*\n*.fb2k-component\n[Dd]ebug/\n[Dd]ebugPublic/\n[Dd]ebug FB2K/\n[Rr]elease/\n[Rr]eleases/\n[Rr]elease FB2K/\nx64/\nx86/\nbld/\n[Bb]in/\n[Oo]bj/\n[Ll]og/\n\n# Visual Studio 2015 cache/options directory\n.vs/\n# Uncomment if you have tasks that create the project's static files in wwwroot\n#wwwroot/\n\n# MSTest test Results\n[Tt]est[Rr]esult*/\n[Bb]uild[Ll]og.*\n\n# NUNIT\n*.VisualState.xml\nTestResult.xml\n\n# Build Results of an ATL Project\n[Dd]ebugPS/\n[Rr]eleasePS/\ndlldata.c\n\n# DNX\nproject.lock.json\nproject.fragment.lock.json\nartifacts/\n\n*_i.c\n*_p.c\n*_i.h\n*.ilk\n*.meta\n*.obj\n*.pch\n*.pdb\n*.pgc\n*.pgd\n*.rsp\n*.sbr\n*.tlb\n*.tli\n*.tlh\n*.tmp\n*.tmp_proj\n*.log\n*.vspscc\n*.vssscc\n.builds\n*.pidb\n*.svclog\n*.scc\n\n# Chutzpah Test files\n_Chutzpah*\n\n# Visual C++ cache files\nipch/\n*.aps\n*.ncb\n*.opendb\n*.opensdf\n*.sdf\n*.cachefile\n*.VC.db\n*.VC.VC.opendb\n\n# Visual Studio profiler\n*.psess\n*.vsp\n*.vspx\n*.sap\n\n# TFS 2012 Local Workspace\n$tf/\n\n# Guidance Automation Toolkit\n*.gpState\n\n# ReSharper is a .NET coding add-in\n_ReSharper*/\n*.[Rr]e[Ss]harper\n*.DotSettings.user\n\n# JustCode is a .NET coding add-in\n.JustCode\n\n# TeamCity is a build add-in\n_TeamCity*\n\n# DotCover is a Code Coverage Tool\n*.dotCover\n\n# Visual Studio code coverage results\n*.coverage\n*.coveragexml\n\n# NCrunch\n_NCrunch_*\n.*crunch*.local.xml\nnCrunchTemp_*\n\n# MightyMoose\n*.mm.*\nAutoTest.Net/\n\n# Web workbench (sass)\n.sass-cache/\n\n# Installshield output folder\n[Ee]xpress/\n\n# DocProject is a documentation generator add-in\nDocProject/buildhelp/\nDocProject/Help/*.HxT\nDocProject/Help/*.HxC\nDocProject/Help/*.hhc\nDocProject/Help/*.hhk\nDocProject/Help/*.hhp\nDocProject/Help/Html2\nDocProject/Help/html\n\n# Click-Once directory\npublish/\n\n# Publish Web Output\n*.[Pp]ublish.xml\n*.azurePubxml\n# TODO: Comment the next line if you want to checkin your web deploy settings\n# but database connection strings (with potential passwords) will be unencrypted\n*.pubxml\n*.publishproj\n\n# Microsoft Azure Web App publish settings. Comment the next line if you want to\n# checkin your Azure Web App publish settings, but sensitive information contained\n# in these scripts will be unencrypted\nPublishScripts/\n\n# NuGet Packages\n*.nupkg\n# The packages folder can be ignored because of Package Restore\n**/packages/*\n# except build/, which is used as an MSBuild target.\n!**/packages/build/\n# Uncomment if necessary however generally it will be regenerated when needed\n#!**/packages/repositories.config\n# NuGet v3's project.json files produces more ignoreable files\n*.nuget.props\n*.nuget.targets\n\n# Microsoft Azure Build Output\ncsx/\n*.build.csdef\n\n# Microsoft Azure Emulator\necf/\nrcf/\n\n# Windows Store app package directories and files\nAppPackages/\nBundleArtifacts/\nPackage.StoreAssociation.xml\n_pkginfo.txt\n\n# Visual Studio cache files\n# files ending in .cache can be ignored\n*.[Cc]ache\n# but keep track of directories ending in .cache\n!*.[Cc]ache/\n\n# Others\nClientBin/\n~$*\n*~\n*.dbmdl\n*.dbproj.schemaview\n*.jfm\n*.pfx\n*.publishsettings\nnode_modules/\norleans.codegen.cs\n\n# Since there are multiple workflows, uncomment next line to ignore bower_components\n# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)\n#bower_components/\n\n# RIA/Silverlight projects\nGenerated_Code/\n\n# Backup & report files from converting an old project file\n# to a newer Visual Studio version. Backup files are not needed,\n# because we have git ;-)\n_UpgradeReport_Files/\nBackup*/\nUpgradeLog*.XML\nUpgradeLog*.htm\n\n# SQL Server files\n*.mdf\n*.ldf\n\n# Business Intelligence projects\n*.rdl.data\n*.bim.layout\n*.bim_*.settings\n\n# Microsoft Fakes\nFakesAssemblies/\n\n# GhostDoc plugin setting file\n*.GhostDoc.xml\n\n# Node.js Tools for Visual Studio\n.ntvs_analysis.dat\n\n# Visual Studio 6 build log\n*.plg\n\n# Visual Studio 6 workspace options file\n*.opt\n\n# Visual Studio LightSwitch build output\n**/*.HTMLClient/GeneratedArtifacts\n**/*.DesktopClient/GeneratedArtifacts\n**/*.DesktopClient/ModelManifest.xml\n**/*.Server/GeneratedArtifacts\n**/*.Server/ModelManifest.xml\n_Pvt_Extensions\n\n# Paket dependency manager\n.paket/paket.exe\npaket-files/\n\n# FAKE - F# Make\n.fake/\n\n# JetBrains Rider\n.idea/\n*.sln.iml\n\n# CodeRush\n.cr/\n\n# Python Tools for Visual Studio (PTVS)\n__pycache__/\n*.pyc\n\n### VisualStudio Patch ###\nbuild/\n"
  },
  {
    "path": ".gitmodules",
    "content": "[submodule \"submodules/acfu-sdk\"]\n\tpath = submodules/acfu-sdk\n\turl = https://github.com/3dyd/acfu-sdk/\n[submodule \"submodules/fmt\"]\n\tpath = submodules/fmt\n\turl = https://github.com/fmtlib/fmt\n\tbranch = release\n[submodule \"submodules/foobar2000\"]\n\tpath = submodules/foobar2000\n\turl = https://github.com/TheQwertiest/foobar2000-sdk\n[submodule \"submodules/pfc\"]\n\tpath = submodules/pfc\n\turl = https://github.com/TheQwertiest/pfc\n[submodule \"submodules/range\"]\n\tpath = submodules/range\n\turl = https://github.com/ericniebler/range-v3\n[submodule \"submodules/span\"]\n\tpath = submodules/span\n\turl = https://github.com/martinmoene/span-lite\n[submodule \"submodules/json\"]\n\tpath = submodules/json\n\turl = https://github.com/nlohmann/json.git\n\tbranch = master\n[submodule \"submodules/wtl\"]\n\tpath = submodules/wtl\n\turl = https://git.code.sf.net/p/wtl/git\n[submodule \"submodules/fb2k_utils\"]\n\tpath = submodules/fb2k_utils\n\turl = https://github.com/TheQwertiest/fb2k_utils.git\n[submodule \"submodules/ring-span\"]\n\tpath = submodules/ring-span\n\turl = https://github.com/martinmoene/ring-span-lite.git\n"
  },
  {
    "path": ".license_index.txt",
    "content": "foobar2000 SDK: other\nfmt: other\nJSON for Modern C++: MIT\nLibSpotify: other\nPFC: zlib\nrange-v3: BSL-1.0\nring-span-lite: BSL-1.0\nspan-lite: BSL-1.0\nWTL: MS-PL\n"
  },
  {
    "path": "CHANGELOG.md",
    "content": "# Changelog\n\n#### Table of Contents\n- [Unreleased](#unreleased)\n- [1.1.3](#113---2021-02-18)\n- [1.1.2](#112---2020-11-03)\n- [1.1.1](#111---2020-10-27)\n- [1.1.0](#110---2020-10-26)\n- [1.0.2](#102---2020-10-04)\n- [1.0.1](#101---2020-10-03)\n- [1.0.0](#100---2020-10-02)\n\n___\n\n## [Unreleased][]\n\n## [1.1.3][] - 2021-02-18\n\n### Fixed\n- Fixed broken import-by-URL handling ([#47](https://github.com/TheQwertiest/foo_spotify/issues/47)).\n- Fixed some issues with keyboard navigation in component menu in Preferences.\n\n## [1.1.2][] - 2020-11-03\n\n### Changed\n- Better Web API handling in attempt to avoid 429 errors:\n  - Pre-emptive batch artist update on album import ([#36](https://github.com/TheQwertiest/foo_spotify/issues/36)).\n\n### Fixed\n- Unreasonably high CPU usage in some scenarios ([#35](https://github.com/TheQwertiest/foo_spotify/issues/35)).\n- Rps limiter is not working ([#34](https://github.com/TheQwertiest/foo_spotify/issues/34)).\n- Extra silence at the end of track ([#33](https://github.com/TheQwertiest/foo_spotify/issues/33)).\n\n## [1.1.1][] - 2020-10-27\n\n### Changed\n- Better Web API handling in attempt to avoid 429 errors:\n  - Pre-emptive batch artist update on playlist import ([#32](https://github.com/TheQwertiest/foo_spotify/issues/32)).\n\n## [1.1.0][] - 2020-10-26\n\n### Added\n- *Play* the artist: adds top tracks for the artist ([#15](https://github.com/TheQwertiest/foo_spotify/issues/15)).\n- `%codec%` metadata field ([#14](https://github.com/TheQwertiest/foo_spotify/issues/14)).\n- More options in `Preferences`:\n  - Cache size configuration ([#23](https://github.com/TheQwertiest/foo_spotify/issues/23)).\n  - Spotify `private mode` option ([#13](https://github.com/TheQwertiest/foo_spotify/issues/13)).\n  - Spotify normalization option ([#12](https://github.com/TheQwertiest/foo_spotify/issues/12)).\n\n### Changed\n- Better Web API handling in attempt to avoid 429 errors:\n  - RPS limit ([#27](https://github.com/TheQwertiest/foo_spotify/issues/27)).\n  - `retry-after` response header handling ([#11](https://github.com/TheQwertiest/foo_spotify/issues/11)).\n  - Pre-emptive batch track update on playlist change ([#30](https://github.com/TheQwertiest/foo_spotify/issues/30)).\n  - Pre-emptive batch artist update on playlist change ([#31](https://github.com/TheQwertiest/foo_spotify/issues/31)).\n- Improved error message when track is not available in user's country ([#8](https://github.com/TheQwertiest/foo_spotify/issues/8)).\n\n### Fixed\n- Can't relogin without closing Preferences dialog ([#24](https://github.com/TheQwertiest/foo_spotify/issues/24)).\n- Dynamic info change is signaled too frequently, despite data being the same ([#22](https://github.com/TheQwertiest/foo_spotify/issues/22)).\n- Can't play tracks when buffering is enabled in fb2k ([#21](https://github.com/TheQwertiest/foo_spotify/issues/21)).\n- Crash: Illegal operation ([#19](https://github.com/TheQwertiest/foo_spotify/issues/19)).\n- Multi-value tags are not displayed correctly ([#17](https://github.com/TheQwertiest/foo_spotify/issues/17)).\n- Can't import playlists with local tracks ([#16](https://github.com/TheQwertiest/foo_spotify/issues/16), [#18](https://github.com/TheQwertiest/foo_spotify/issues/18)).\n\n## [1.0.2][] - 2020-10-04\n\n### Added\n- Proxy support ([#6](https://github.com/TheQwertiest/foo_spotify/issues/6)).\n- Adjust bit-rate via `Preferences` ([#5](https://github.com/TheQwertiest/foo_spotify/issues/5)).\n- Bit-rate metadata for playing track ([#4](https://github.com/TheQwertiest/foo_spotify/issues/4)).\n\n### Fixed\n- Fails to open track that has null `preview_url` ([#3](https://github.com/TheQwertiest/foo_spotify/issues/3)).\n\n## [1.0.1][] - 2020-10-03\n\n### Fixed\n- LibSpotify login doesn't always work ([#1](https://github.com/TheQwertiest/foo_spotify/issues/1)).\n\n## [1.0.0][] - 2020-10-02\nInitial release.\n\n[unreleased]: https://github.com/TheQwertiest/foo_spotify/compare/v1.1.3...HEAD\n[1.1.3]: https://github.com/TheQwertiest/foo_spotify/compare/v1.1.2...v1.1.3\n[1.1.2]: https://github.com/TheQwertiest/foo_spotify/compare/v1.1.1...v1.1.2\n[1.1.1]: https://github.com/TheQwertiest/foo_spotify/compare/v1.1.0...v1.1.1\n[1.1.0]: https://github.com/TheQwertiest/foo_spotify/compare/v1.0.2...v1.1.0\n[1.0.2]: https://github.com/TheQwertiest/foo_spotify/compare/v1.0.1...v1.0.2\n[1.0.1]: https://github.com/TheQwertiest/foo_spotify/compare/v1.0.0...v1.0.1\n[1.0.0]: https://github.com/TheQwertiest/foo_spotify/commits/master\n"
  },
  {
    "path": "LICENSE",
    "content": "MIT License\n\nCopyright (c) 2018-2020 Yuri Shutenko\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n"
  },
  {
    "path": "README.md",
    "content": "# Spotify Integration\n[![version][version_badge]][changelog] [![Build status][appveyor_badge]](https://ci.appveyor.com/project/TheQwertiest/foo-spotify/branch/master) [![CodeFactor][codefactor_badge]](https://www.codefactor.io/repository/github/theqwertiest/foo_spotify/overview/master) [![Codacy Badge][codacy_badge]](https://www.codacy.com/gh/TheQwertiest/foo_spotify/dashboard?utm_source=github.com&amp;utm_medium=referral&amp;utm_content=TheQwertiest/foo_spotify&amp;utm_campaign=Badge_Grade) \n\n**!!! This component is no longer being developed. See [#68](https://github.com/TheQwertiest/foo_spotify/issues/68) for more info !!!**\n\nThis is a component for the [foobar2000](https://www.foobar2000.org) audio player, which allows to play tracks from Spotify.\n\nVisit [component homepage](https://theqwertiest.github.io/foo_spotify/) for more info.\n\n[changelog]: CHANGELOG.md\n[version_badge]: https://img.shields.io/github/release/theqwertiest/foo_spotify.svg\n[appveyor_badge]: https://ci.appveyor.com/api/projects/status/t5bhoxmfgavhq81m/branch/master?svg=true\n[codacy_badge]: https://app.codacy.com/project/badge/Grade/c2d3b3a99ce640ad8c1512784e15910f\n[codefactor_badge]: https://www.codefactor.io/repository/github/theqwertiest/foo_spotify/badge/master\n"
  },
  {
    "path": "THIRD_PARTY_NOTICES.md",
    "content": "Spotify Integration uses third-party libraries or other resources that may\nbe distributed under licenses different than the Spotify Integration software.\nThe linked notices are provided for information only.\n\n- [foobar2000 SDK - other](licenses/foobar2000%20SDK.txt)\n- [fmt - other](licenses/fmt.txt)\n- [JSON for Modern C++ - MIT](licenses/JSON%20for%20Modern%20C%2B%2B.txt)\n- [LibSpotify - other](licenses/LibSpotify.txt)\n- [PFC - zlib](licenses/PFC.txt)\n- [range-v3 - BSL-1.0](licenses/range-v3.txt)\n- [ring-span-lite - BSL-1.0](licenses/ring-span-lite.txt)\n- [span-lite - BSL-1.0](licenses/span-lite.txt)\n- [WTL - MS-PL](licenses/WTL.txt)\n"
  },
  {
    "path": "VERSION",
    "content": "1.1.4-beta\n"
  },
  {
    "path": "foo_spotify/.clang-format",
    "content": "﻿---\nBasedOnStyle: Mozilla\nAccessModifierOffset: '-4'\nAlwaysBreakAfterDefinitionReturnType: 'false'\nAlignAfterOpenBracket: Align\nAlignConsecutiveAssignments: 'false'\nAlignConsecutiveMacros: 'true'\nAlignEscapedNewlines: Left\nAlignOperands: 'true'\nAllowShortBlocksOnASingleLine: 'false'\nAllowShortCaseLabelsOnASingleLine: 'false'\nAllowShortFunctionsOnASingleLine: None\nAllowShortIfStatementsOnASingleLine: 'false'\nAllowShortLoopsOnASingleLine: 'false'\nAlwaysBreakAfterReturnType: None\nAlwaysBreakTemplateDeclarations: 'true'\nBinPackParameters: 'true'\nBreakBeforeBinaryOperators: NonAssignment\nBreakBeforeBraces: Allman\nBreakBeforeInheritanceComma: 'true'\nBreakConstructorInitializers: BeforeComma\nColumnLimit: '0'\nConstructorInitializerIndentWidth: '4' \nContinuationIndentWidth: '4'\nCpp11BracedListStyle: 'false'\nFixNamespaceComments: 'true'\nIncludeBlocks: Regroup\nIncludeCategories: \n  # precompiled headers\n  - Regex:           '^<stdafx.h|pch.h|precompiled.h>'\n    Priority:        -1\n  # \"header\"\n  - Regex:           '\"[[:alnum:]_]+'\n    Priority:        1\n  # <dependency/header>\n  - Regex:           '^<(acfu-sdk|cpprest|columns_ui-sdk|fmt|foobar2000|js|libspotify|nlohmann|nonstd|range|tim|qwr)/'\n    Priority:        4 \n  # <dependency_header>\n  - Regex:           '^<(atl.*\\.h)>'\n    Priority:        5\n  # <subdir/header.h>|<subdir/header.hpp>\n  - Regex:           '<[[:alnum:]_]+/.+\\.(h|hpp)>'\n    Priority:        2\n  # <header.h>|<header.hpp>\n  - Regex:           '<[[:alnum:]_]+\\.(h|hpp)>'\n    Priority:        3\n  # <header>\n  - Regex:           '<[[:alnum:]_]+>'\n    Priority:        6\nIncludeIsMainRegex: '$'\nIndentCaseLabels: false\nIndentPPDirectives: AfterHash\nIndentWidth: '4'\nIndentWrappedFunctionNames: false\nLanguage: Cpp\nMacroBlockBegin: \"^BEGIN_*\"\nMacroBlockEnd: \"^END_*\"\nMaxEmptyLinesToKeep: '1'\nPointerAlignment: Left\nReflowComments: 'true'\nSortIncludes: 'false'\nSpaceAfterCStyleCast: 'false'\nSpaceAfterTemplateKeyword : 'true'\nSpaceBeforeAssignmentOperators: 'true'\nSpaceBeforeParens: ControlStatements\nSpaceBeforeRangeBasedForLoopColon: 'false'\nSpaceInEmptyParentheses: 'false'\nSpacesInAngles: 'false'\nSpacesInCStyleCastParentheses: 'false'\nSpacesInParentheses: 'true'\nSpacesInSquareBrackets: 'false'\nSortIncludes: 'true'\nStandard: Cpp11\nTabWidth: '4'\nTypenameMacros: ['STDMETHOD', 'STDMETHODIMP_']\nUseTab: Never\n\n...\n"
  },
  {
    "path": "foo_spotify/.clang-tidy",
    "content": "Checks: '-*,\n         bugprone-*,\n         cert-*,\n         clang-analyzer-*,\n         google-*,\n         -google-build-using-namespace,\n         -google-explicit-constructor,\n         -google-readability-todo,\n         -google-runtime-references,\n         hicpp-*,\n         -hicpp-explicit-conversions,\n         -hicpp-no-array-decay,\n         -hicpp-signed-bitwise,\n         -hicpp-uppercase-literal-suffix,\n         misc-*,\n         -misc-non-private-member-variables-in-classes,\n         llvm-*,\n         -llvm-include-order,\n         -llvm-header-guard,\n         -llvm-namespace-comment,\n         modernize-*,\n         -modernize-use-trailing-return-type,\n         performance-*,\n         portability-*,\n         readability-*,\n         -readability-else-after-return,\n         -readability-implicit-bool-conversion,\n         -readability-magic-numbers,\n         -readability-named-parameter,\n         -readability-redundant-access-specifiers,\n         -readability-uppercase-literal-suffix'\n"
  },
  {
    "path": "foo_spotify/backend/audio_buffer.cpp",
    "content": "#include <stdafx.h>\n\n#include \"audio_buffer.h\"\n\n#include <utils/abort_manager.h>\n\nnamespace sptf\n{\n\nAudioBuffer::AudioBuffer( AbortManager& abortManager )\n    : abortManager_( abortManager )\n{\n}\n\nbool AudioBuffer::write( AudioChunkHeader header, const uint16_t* data )\n{\n    {\n        std::lock_guard lock( posMutex_ );\n\n        const size_t readPos = readPos_;\n        const size_t writePos = writePos_;\n        const size_t waterMark = waterMark_;\n        const size_t writeSize = k_headerSizeInU16 + header.size;\n\n        const auto writeData = [&]( size_t writePos ) {\n            const auto curBufferPos = begin_ + writePos;\n            std::copy( &header, &header + 1, reinterpret_cast<AudioChunkHeader*>( curBufferPos ) );\n            std::copy( data, data + header.size, curBufferPos + k_headerSizeInU16 );\n        };\n\n        // TODO: simplify the code\n        if ( writePos >= readPos ) // write leads\n        {\n            if ( size_ - writePos >= writeSize )\n            {\n                writeData( writePos );\n\n                writePos_ = writePos + writeSize;\n                waterMark_ = size_;\n            }\n            else // wrap-around\n            {\n                if ( !readPos || readPos - 1 < writeSize )\n                {\n                    return false;\n                }\n\n                writeData( 0 );\n\n                writePos_ = writeSize;\n                waterMark_ = writePos;\n            }\n        }\n        else // read leads\n        {\n            if ( readPos - 1 - writePos < writeSize )\n            {\n                return false;\n            }\n\n            writeData( writePos );\n\n            writePos_ = writePos + writeSize;\n        }\n    }\n\n    dataCv_.notify_all();\n    return true;\n}\n\nvoid AudioBuffer::write_end()\n{\n    uint16_t dummy{};\n    write( AudioChunkHeader{ 0, 0, 0, 1 }, &dummy );\n}\n\nbool AudioBuffer::has_data() const\n{\n    std::lock_guard lock( posMutex_ );\n\n    return has_data_no_lock();\n}\n\nbool AudioBuffer::wait_for_data( abort_callback& abort )\n{\n    const auto abortableScope = abortManager_.GetAbortableScope( [&] { dataCv_.notify_all(); }, abort );\n\n    std::unique_lock lock( posMutex_ );\n    dataCv_.wait( lock, [&] {\n        return ( has_data_no_lock() || abort.is_aborting() );\n    } );\n    return has_data_no_lock();\n}\n\nvoid AudioBuffer::clear()\n{\n    {\n        std::lock_guard lock( posMutex_ );\n\n        readPos_ = 0;\n        writePos_ = 0;\n        waterMark_ = size_;\n    }\n    dataCv_.notify_all();\n}\n\nbool AudioBuffer::has_data_no_lock() const\n{\n    return ( readPos_ != writePos_ );\n}\n\n} // namespace sptf\n"
  },
  {
    "path": "foo_spotify/backend/audio_buffer.h",
    "content": "#pragma once\n\n#include <nonstd/span.hpp>\n\n#include <array>\n#include <atomic>\n#include <mutex>\n\nnamespace sptf\n{\n\nclass AbortManager;\n\n// TODO: bench and replace with lock-free if needed\nclass AudioBuffer\n{\n    static constexpr size_t k_maxBufferSize = 8UL * 1024 * 1024;\n\npublic:\n#pragma pack( push )\n#pragma pack( 1 )\n    struct AudioChunkHeader\n    {\n        uint32_t sampleRate;\n        uint16_t channels;\n        uint32_t size;\n        uint16_t eof;\n    };\n#pragma pack( pop )\n\nprivate:\n    static constexpr size_t k_headerSizeInU16 = sizeof( AudioChunkHeader ) / sizeof( uint16_t );\n\npublic:\n    AudioBuffer( AbortManager& abortManager );\n    ~AudioBuffer() = default;\n\n    bool write( AudioChunkHeader header, const uint16_t* data );\n    void write_end();\n\n    template <typename Fn>\n    bool read( Fn fn );\n\n    bool has_data() const;\n    bool wait_for_data( abort_callback& abort );\n\n    void clear();\n\nprivate:\n    bool has_data_no_lock() const;\n\nprivate:\n    AbortManager& abortManager_;\n\n    std::array<uint16_t, k_maxBufferSize> buffer_;\n    uint16_t* begin_ = buffer_.data();\n    static constexpr size_t size_ = k_maxBufferSize;\n\n    mutable std::mutex posMutex_;\n    std::condition_variable dataCv_;\n\n    size_t readPos_ = 0;\n    size_t writePos_ = 0;\n    size_t waterMark_ = size_;\n};\n\ntemplate <typename Fn>\nbool sptf::AudioBuffer::read( Fn fn )\n{\n    std::lock_guard lock( posMutex_ );\n\n    size_t readPos = readPos_;\n    const size_t writePos = writePos_;\n    const size_t waterMark = waterMark_;\n\n    if ( readPos == writePos )\n    {\n        return false;\n    }\n\n    readPos = ( readPos == waterMark ? 0 : readPos );\n\n    const auto curBufferPos = begin_ + readPos;\n    fn( *reinterpret_cast<AudioChunkHeader*>( curBufferPos ), curBufferPos + k_headerSizeInU16 );\n\n    readPos_ = readPos + k_headerSizeInU16 + reinterpret_cast<AudioChunkHeader*>( curBufferPos )->size;\n\n    return true;\n}\n\n} // namespace sptf\n"
  },
  {
    "path": "foo_spotify/backend/libspotify_backend.cpp",
    "content": "#include <stdafx.h>\n\n#include \"libspotify_backend.h\"\n\n#include <backend/libspotify_key.h>\n#include <backend/spotify_instance.h>\n#include <fb2k/advanced_config.h>\n#include <ui/ui_not_auth.h>\n#include <utils/abort_manager.h>\n#include <utils/cred_prompt.h>\n\n#include <component_paths.h>\n\n#include <libspotify/api.h>\n#include <qwr/abort_callback.h>\n#include <qwr/error_popup.h>\n#include <qwr/fb2k_adv_config.h>\n#include <qwr/thread_helpers.h>\n#include <qwr/winapi_error_helpers.h>\n\n#include <filesystem>\n#include <fstream>\n#include <tuple>\n\n// see https://github.com/mopidy/mopidy-spotify for tips and stuff\n\nnamespace fs = std::filesystem;\n\nusing namespace sptf;\n\nnamespace sptf\n{\n\nLibSpotify_Backend::LibSpotify_Backend( AbortManager& abortManager )\n    : abortManager_( abortManager )\n    , audioBuffer_( abortManager )\n{\n    if ( const auto settingsPath = path::LibSpotifySettings(); !fs::exists( settingsPath ) )\n    {\n        fs::create_directories( settingsPath );\n    }\n    // TODO: add fs error/exception checks\n\n    const auto cachePath = path::LibSpotifyCache().u8string();\n    const auto settingsPath = path::LibSpotifySettings().u8string();\n\n    config_.api_version = SPOTIFY_API_VERSION,\n    config_.cache_location = cachePath.c_str();\n    config_.settings_location = settingsPath.c_str();\n    config_.application_key = g_appkey;\n    config_.application_key_size = sizeof( g_appkey );\n    config_.user_agent = \"foobar2000-foo_spotify-\" SPTF_VERSION;\n    config_.userdata = this;\n    config_.callbacks = &callbacks_;\n\n    const auto proxyUrl = sptf::config::advanced::network_proxy.GetValue();\n    const auto proxyUsername = sptf::config::advanced::network_proxy_username.GetValue();\n    const auto proxyPassword = sptf::config::advanced::network_proxy_password.GetValue();\n    if ( !proxyUrl.empty() )\n    {\n        config_.proxy = proxyUrl.c_str();\n        if ( !proxyUsername.empty() && !proxyPassword.empty() )\n        {\n            config_.proxy_username = proxyUsername.c_str();\n            config_.proxy_password = proxyPassword.c_str();\n        }\n    }\n\n    /*\n    config_.tracefile = ...;\n    */\n\n#define SPTF_ASSIGN_CALLBACK( callbacks, name )                                                      \\\n    callbacks.name = []( sp_session * pSession, auto... args ) -> auto                               \\\n    { /** sp_session_userdata is assumed to be thread safe. */                                       \\\n        return static_cast<LibSpotify_Backend*>( sp_session_userdata( pSession ) )->name( args... ); \\\n    }\n\n    // dummy callbacks are needed to avoid libspotify crashes on sp_session_release\n#define SPTF_ASSIGN_DUMMY_CALLBACK( callbacks, name ) \\\n    callbacks.name = []( auto... ) {}\n\n    SPTF_ASSIGN_CALLBACK( callbacks_, logged_in );\n    SPTF_ASSIGN_DUMMY_CALLBACK( callbacks_, logged_out );\n    SPTF_ASSIGN_DUMMY_CALLBACK( callbacks_, metadata_updated );\n    SPTF_ASSIGN_DUMMY_CALLBACK( callbacks_, connection_error );\n    SPTF_ASSIGN_CALLBACK( callbacks_, message_to_user );\n    SPTF_ASSIGN_CALLBACK( callbacks_, notify_main_thread );\n    SPTF_ASSIGN_CALLBACK( callbacks_, music_delivery );\n    SPTF_ASSIGN_CALLBACK( callbacks_, play_token_lost );\n    SPTF_ASSIGN_CALLBACK( callbacks_, log_message );\n    SPTF_ASSIGN_CALLBACK( callbacks_, end_of_track );\n    SPTF_ASSIGN_DUMMY_CALLBACK( callbacks_, streaming_error );\n    SPTF_ASSIGN_DUMMY_CALLBACK( callbacks_, userinfo_updated );\n    SPTF_ASSIGN_DUMMY_CALLBACK( callbacks_, start_playback );\n    SPTF_ASSIGN_DUMMY_CALLBACK( callbacks_, stop_playback );\n    SPTF_ASSIGN_DUMMY_CALLBACK( callbacks_, get_audio_buffer_stats );\n    SPTF_ASSIGN_DUMMY_CALLBACK( callbacks_, offline_status_updated );\n    SPTF_ASSIGN_DUMMY_CALLBACK( callbacks_, offline_error );\n    SPTF_ASSIGN_DUMMY_CALLBACK( callbacks_, credentials_blob_updated );\n    SPTF_ASSIGN_CALLBACK( callbacks_, connectionstate_updated );\n    SPTF_ASSIGN_DUMMY_CALLBACK( callbacks_, scrobble_error );\n    SPTF_ASSIGN_CALLBACK( callbacks_, private_session_mode_changed );\n\n#undef SPTF_ASSIGN_DUMMY_CALLBACK\n#undef SPTF_ASSIGN_CALLBACK\n\n    // TODO: check if `sp_playlist_add_callbacks` works when implementing playlist handling\n\n    {\n        std::lock_guard lock( apiMutex_ );\n        const auto sp = sp_session_create( &config_, &pSpSession_ );\n        if ( sp != SP_ERROR_OK )\n        {\n            throw qwr::QwrException( fmt::format( \"sp_session_create failed: {}\", sp_error_message( sp ) ) );\n        }\n    }\n\n    StartEventLoopThread();\n\n    RefreshBitrate();\n    RefreshNormalization();\n    RefreshCacheSize();\n}\n\nvoid LibSpotify_Backend::Finalize()\n{\n    StopEventLoopThread();\n\n    {\n        std::lock_guard lk( backendUsersMutex_ );\n\n        for ( auto& pInput: backendUsers_ )\n        {\n            pInput->Finalize();\n        }\n    }\n\n    {\n        std::lock_guard lock( apiMutex_ );\n        sp_session_player_unload( pSpSession_ );\n        sp_session_release( pSpSession_ );\n    }\n}\n\nvoid LibSpotify_Backend::RegisterBackendUser( LibSpotify_BackendUser& input )\n{\n    std::lock_guard lk( backendUsersMutex_ );\n\n    assert( !backendUsers_.count( &input ) );\n    backendUsers_.emplace( &input );\n}\n\nvoid LibSpotify_Backend::UnregisterBackendUser( LibSpotify_BackendUser& input )\n{\n    std::lock_guard lk( backendUsersMutex_ );\n\n    assert( backendUsers_.count( &input ) );\n    backendUsers_.erase( &input );\n}\n\nsp_session* LibSpotify_Backend::GetInitializedSpSession( abort_callback& p_abort )\n{\n    assert( pSpSession_ );\n    if ( !Relogin( p_abort ) )\n    {\n        ::fb2k::inMainThread( [&] {\n            playback_control::get()->stop();\n            ui::NotAuthHandler::Get().ShowDialog();\n        } );\n        throw qwr::QwrException( \"Failed to get authenticated Spotify session\" );\n    }\n\n    return pSpSession_;\n}\n\nsp_session* LibSpotify_Backend::GetWhateverSpSession()\n{\n    assert( pSpSession_ );\n    return pSpSession_;\n}\n\nbool LibSpotify_Backend::Relogin( abort_callback& abort )\n{\n    {\n        std::lock_guard lock( loginMutex_ );\n\n        if ( loginStatus_ == LoginStatus::logged_out )\n        {\n            return false;\n        }\n\n        if ( loginStatus_ == LoginStatus::uninitialized )\n        {\n            loginStatus_ = LoginStatus::login_in_process;\n\n            const auto spRet = [&] {\n                std::lock_guard lock( apiMutex_ );\n                return sp_session_relogin( pSpSession_ );\n            }();\n            if ( spRet == SP_ERROR_NO_CREDENTIALS )\n            {\n                loginStatus_ = LoginStatus::logged_out;\n                return false;\n            }\n        }\n    }\n\n    auto retStatus = WaitForLoginStatusUpdate( abort );\n    return ( retStatus.has_value() ? *retStatus : false );\n}\n\nbool LibSpotify_Backend::LoginWithUI( HWND hWnd )\n{\n    // TODO: add abortable as a method argument\n    assert( core_api::assert_main_thread() );\n\n    {\n        std::lock_guard lock( loginMutex_ );\n        assert( loginStatus_ == LoginStatus::logged_out );\n        loginStatus_ = LoginStatus::login_in_process;\n        isLoginBad_ = false;\n    }\n\n    std::optional<bool> retStatus;\n    do\n    {\n        const auto wasLoginBad = [&] {\n            std::lock_guard lock( loginMutex_ );\n            return isLoginBad_;\n        }();\n\n        auto cpr = ShowCredentialsDialog( hWnd, wasLoginBad ? sp_error_message( SP_ERROR_BAD_USERNAME_OR_PASSWORD ) : nullptr );\n        if ( cpr->cancelled )\n        {\n            {\n                std::lock_guard lock( loginMutex_ );\n                loginStatus_ = LoginStatus::logged_out;\n            }\n            loginCv_.notify_all();\n            return false;\n        }\n\n        {\n            std::lock_guard lock( apiMutex_ );\n            sp_session_login( pSpSession_, cpr->un.data(), cpr->pw.data(), true, nullptr );\n        }\n\n        qwr::TimedAbortCallback tac( fmt::format( \"{}: {}\", SPTF_UNDERSCORE_NAME, \"LibSpotify wait for login update\" ) );\n        retStatus = WaitForLoginStatusUpdate( tac );\n    } while ( retStatus.has_value() && !*retStatus );\n\n    return ( retStatus.has_value() ? *retStatus : false );\n}\n\nvoid LibSpotify_Backend::LogoutAndForget( abort_callback& abort )\n{\n    {\n        std::lock_guard lgLogin( loginMutex_ );\n        if ( loginStatus_ != LoginStatus::logged_in )\n        {\n            return;\n        }\n\n        loginStatus_ = LoginStatus::logout_in_process;\n    }\n\n    {\n        std::lock_guard lgApi( apiMutex_ );\n        sp_session_logout( pSpSession_ );\n        sp_session_forget_me( pSpSession_ );\n    }\n\n    WaitForLoginStatusUpdate( abort );\n}\n\nstd::string LibSpotify_Backend::GetLoggedInUserName()\n{\n    {\n        std::lock_guard lock( loginMutex_ );\n        if ( loginStatus_ != LoginStatus::logged_in )\n        {\n            return \"<error: user is not logged in>\";\n        }\n    }\n\n    std::lock_guard lock( apiMutex_ );\n\n    // `sp_user_display_name` always returns canonical name:\n    // https://stackoverflow.com/questions/23797162/sp-user-display-name-always-returns-canonical-name-even-when-user-is-loaded\n\n    const char* email = sp_session_user_name( pSpSession_ );\n    if ( !email )\n    {\n        return \"<error: user name could not be fetched>\";\n    }\n\n    return email;\n}\n\nvoid LibSpotify_Backend::RefreshBitrate()\n{\n    std::lock_guard lock( apiMutex_ );\n    const auto sp = sp_session_preferred_bitrate( pSpSession_, static_cast<sp_bitrate>( static_cast<uint8_t>( config::preferred_bitrate.GetValue() ) ) );\n    if ( sp != SP_ERROR_OK )\n    {\n        qwr::ReportErrorWithPopup( SPTF_UNDERSCORE_NAME, fmt::format( \"sp_session_preferred_bitrate failed:\\n{}\", sp_error_message( sp ) ) );\n    }\n}\n\nvoid LibSpotify_Backend::RefreshNormalization()\n{\n    std::lock_guard lock( apiMutex_ );\n    const auto sp = sp_session_set_volume_normalization( pSpSession_, config::enable_normalization );\n    if ( sp != SP_ERROR_OK )\n    {\n        qwr::ReportErrorWithPopup( SPTF_UNDERSCORE_NAME, fmt::format( \"sp_session_set_volume_normalization failed:\\n{}\", sp_error_message( sp ) ) );\n    }\n}\n\nvoid LibSpotify_Backend::RefreshPrivateMode()\n{\n    {\n        std::lock_guard lock( loginMutex_ );\n        if ( loginStatus_ != LoginStatus::logged_in )\n        { // private session can be set only in logged in session\n            return;\n        }\n    }\n\n    {\n        std::lock_guard lock( apiMutex_ );\n        RefreshPrivateModeNonBlocking();\n    }\n}\n\nvoid LibSpotify_Backend::RefreshCacheSize()\n{\n    const auto sizeInMb = config::libspotify_cache_size_in_mb.GetValue();\n    const auto sizeInPercent = config::libspotify_cache_size_in_percent.GetValue();\n\n    const auto cacheSize = [sizeInMb, sizeInPercent]() -> uint32_t {\n        if ( !sizeInMb && ( sizeInPercent == 10 || !sizeInPercent ) )\n        { // 0 - default LibSpotify behaviour\n            return 0;\n        }\n\n        uint64_t dummy1;\n        uint64_t dummy2;\n        uint64_t freeBytes;\n        auto bRet = GetDiskFreeSpaceEx( L\"C:\",\n                                        (PULARGE_INTEGER)&dummy1,\n                                        (PULARGE_INTEGER)&dummy2,\n                                        (PULARGE_INTEGER)&freeBytes );\n        qwr::error::CheckWinApi( bRet, \"GetDiskFreeSpaceEx\" );\n        const auto freeMb = ( uint32_t )( freeBytes / ( 1024 * 1024 ) );\n\n        if ( !sizeInPercent )\n        {\n            return std::min( sizeInMb, freeMb );\n        }\n        else\n        {\n            const auto freeSpacePercented = ( uint32_t )( freeMb * ( 1.0 / sizeInPercent ) );\n            if ( sizeInMb )\n            {\n                return std::min( sizeInMb, freeSpacePercented );\n            }\n            else\n            {\n                return freeSpacePercented;\n            }\n        }\n    }();\n\n    std::lock_guard lock( apiMutex_ );\n    const auto sp = sp_session_set_cache_size( pSpSession_, cacheSize );\n    if ( sp != SP_ERROR_OK )\n    {\n        qwr::ReportErrorWithPopup( SPTF_UNDERSCORE_NAME, fmt::format( \"sp_session_set_cache_size failed:\\n{}\", sp_error_message( sp ) ) );\n    }\n}\n\nvoid LibSpotify_Backend::EventLoopThread()\n{\n    int nextTimeout = INFINITE;\n    while ( true )\n    {\n        {\n            std::unique_lock lock( workerMutex_ );\n\n            while ( !hasEvents_ && !shouldStopEventLoop_ )\n            {\n                const auto ret = eventLoopCv_.wait_for( lock, std::chrono::milliseconds( nextTimeout ) );\n                if ( std::cv_status::timeout == ret )\n                {\n                    break;\n                }\n            }\n\n            if ( shouldStopEventLoop_ )\n            {\n                return;\n            }\n            hasEvents_ = false;\n        }\n\n        std::lock_guard lock( apiMutex_ );\n        sp_session_process_events( pSpSession_, &nextTimeout );\n    }\n}\n\nvoid LibSpotify_Backend::StartEventLoopThread()\n{\n    assert( !pWorker_ );\n    pWorker_ = std::make_unique<std::thread>( &LibSpotify_Backend::EventLoopThread, this );\n    qwr::SetThreadName( *pWorker_, \"SPTF Event Loop\" );\n}\n\nvoid LibSpotify_Backend::StopEventLoopThread()\n{\n    if ( !pWorker_ )\n    {\n        return;\n    }\n\n    {\n        std::unique_lock<std::mutex> lock( workerMutex_ );\n        shouldStopEventLoop_ = true;\n    }\n    eventLoopCv_.notify_all();\n\n    if ( pWorker_->joinable() )\n    {\n        pWorker_->join();\n    }\n    pWorker_.reset();\n}\n\nstd::optional<bool> LibSpotify_Backend::WaitForLoginStatusUpdate( abort_callback& abort )\n{\n    const auto abortableScope = abortManager_.GetAbortableScope( [&] { loginCv_.notify_all(); }, abort );\n\n    std::unique_lock lock( loginMutex_ );\n\n    loginCv_.wait( lock, [&] {\n        return ( ( loginStatus_ != LoginStatus::login_in_process\n                   && loginStatus_ != LoginStatus::logout_in_process )\n                 || abort.is_aborting() );\n    } );\n    if ( abort.is_aborting() )\n    {\n        return std::nullopt;\n    }\n\n    return ( loginStatus_ == LoginStatus::logged_in );\n}\n\nvoid LibSpotify_Backend::RefreshPrivateModeNonBlocking()\n{\n    const auto sp = sp_session_set_private_session( pSpSession_, config::enable_private_mode );\n    if ( sp != SP_ERROR_OK )\n    {\n        qwr::ReportErrorWithPopup( SPTF_UNDERSCORE_NAME, fmt::format( \"sp_session_set_private_session failed:\\n{}\", sp_error_message( sp ) ) );\n    }\n}\n\nvoid LibSpotify_Backend::AcquireDecoder( void* owner )\n{\n    std::lock_guard lk( decoderOwnerMutex_ );\n    if ( pDecoderOwner_ && pDecoderOwner_ != owner )\n    {\n        throw exception_io_data( \"Someone else is already decoding: Spotify does not support multiple concurrent decoders\" );\n    }\n\n    pDecoderOwner_ = owner;\n}\n\nvoid LibSpotify_Backend::ReleaseDecoder( void* owner )\n{\n    (void)owner;\n\n    std::lock_guard lk( decoderOwnerMutex_ );\n    assert( owner == pDecoderOwner_ );\n    pDecoderOwner_ = nullptr;\n}\n\nAudioBuffer& LibSpotify_Backend::GetAudioBuffer()\n{\n    return audioBuffer_;\n}\n\nvoid LibSpotify_Backend::log_message( const char* error )\n{\n    FB2K_console_formatter() << SPTF_UNDERSCORE_NAME \" (log): \" << error;\n}\n\nvoid LibSpotify_Backend::logged_in( sp_error error )\n{\n    if ( SP_ERROR_OK == error )\n    {\n        return;\n    }\n\n    if ( SP_ERROR_BAD_USERNAME_OR_PASSWORD == error )\n    {\n        std::lock_guard lock( loginMutex_ );\n        if ( loginStatus_ == LoginStatus::login_in_process )\n        {\n            isLoginBad_ = true;\n            loginStatus_ = LoginStatus::logged_out;\n        }\n    }\n    else\n    {\n        {\n            std::lock_guard lock( loginMutex_ );\n            loginStatus_ = LoginStatus::uninitialized;\n        }\n        qwr::ReportErrorWithPopup( SPTF_NAME, fmt::format( \"Failed to login:\\n{}\", sp_error_message( error ) ) );\n    }\n}\n\nvoid LibSpotify_Backend::message_to_user( const char* message )\n{\n    qwr::ReportErrorWithPopup( SPTF_NAME, message );\n}\n\nvoid LibSpotify_Backend::notify_main_thread()\n{\n    {\n        std::unique_lock lock( workerMutex_ );\n        hasEvents_ = true;\n    }\n\n    eventLoopCv_.notify_all();\n}\n\nint LibSpotify_Backend::music_delivery( const sp_audioformat* format, const void* frames, int num_frames )\n{\n    if ( !num_frames )\n    {\n        audioBuffer_.clear();\n        return 0;\n    }\n\n    assert( frames );\n    if ( num_frames == 22050 && !*(uint16_t*)frames )\n    {   // a dirty hack to remove a 1 seconds silence that libspotify pads the end of a track with\n        // See: https://github.com/mopidy/mopidy-spotify/pull/269\n        // and https://stackoverflow.com/questions/26014520/libspotify-c-sending-zeros-at-the-end-of-track\n        return num_frames;\n    }\n\n    if ( !audioBuffer_.write( AudioBuffer::AudioChunkHeader{ (uint16_t)format->sample_rate,\n                                                             (uint16_t)format->channels,\n                                                             ( uint16_t )( num_frames * format->channels ) },\n                              static_cast<const uint16_t*>( frames ) ) )\n    {\n        return 0;\n    }\n\n    return num_frames;\n}\n\nvoid LibSpotify_Backend::end_of_track()\n{\n    audioBuffer_.write_end();\n}\n\nvoid LibSpotify_Backend::play_token_lost()\n{\n    ::fb2k::inMainThread2( [&] {\n        playback_control::get()->pause( true );\n    } );\n    qwr::ReportErrorWithPopup( SPTF_NAME, \"Playback has been paused because your Spotify account is being used somewhere else.\" );\n}\n\nvoid LibSpotify_Backend::connectionstate_updated()\n{\n    switch ( sp_session_connectionstate( pSpSession_ ) )\n    {\n    case SP_CONNECTION_STATE_LOGGED_IN:\n    case SP_CONNECTION_STATE_OFFLINE:\n    {\n        {\n            std::lock_guard lock( loginMutex_ );\n            loginStatus_ = LoginStatus::logged_in;\n        }\n        loginCv_.notify_all();\n\n        RefreshPrivateModeNonBlocking();\n        break;\n    }\n    case SP_CONNECTION_STATE_LOGGED_OUT:\n    {\n        {\n            std::lock_guard lock( loginMutex_ );\n            if ( loginStatus_ == LoginStatus::login_in_process )\n            { // possible when invalid user/pass are supplied\n                break;\n            }\n            loginStatus_ = LoginStatus::logged_out;\n        }\n        loginCv_.notify_all();\n        break;\n    }\n    default:\n    {\n        break;\n    }\n    }\n}\n\nvoid LibSpotify_Backend::private_session_mode_changed( bool is_private )\n{ // in case private mode expired\n    if ( is_private == config::enable_private_mode )\n    {\n        return;\n    }\n    RefreshPrivateModeNonBlocking();\n}\n\n} // namespace sptf\n"
  },
  {
    "path": "foo_spotify/backend/libspotify_backend.h",
    "content": "#pragma once\n\n#include <backend/audio_buffer.h>\n#include <backend/libspotify_backend_user.h>\n#include <fb2k/config.h>\n\n#include <libspotify/api.h>\n\n#include <condition_variable>\n#include <optional>\n#include <unordered_set>\n\nnamespace sptf\n{\n\nclass AbortManager;\n\nclass LibSpotify_Backend\n{\npublic:\n    LibSpotify_Backend( AbortManager& abortManager );\n    LibSpotify_Backend( const LibSpotify_Backend& ) = delete;\n    LibSpotify_Backend( LibSpotify_Backend&& ) = delete;\n    ~LibSpotify_Backend() = default;\n\n    void Finalize();\n\n    void RegisterBackendUser( LibSpotify_BackendUser& backendUser );\n    void UnregisterBackendUser( LibSpotify_BackendUser& backendUser );\n\n    void AcquireDecoder( void* owner );\n    void ReleaseDecoder( void* owner );\n\n    AudioBuffer& GetAudioBuffer();\n\n    sp_session* GetInitializedSpSession( abort_callback& abort );\n    sp_session* GetWhateverSpSession();\n\n    template <typename Fn, typename... Args>\n    auto ExecSpMutex( Fn func, Args&&... args ) -> decltype( auto )\n    {\n        std::lock_guard lock( apiMutex_ );\n        return func( std::forward<Args>( args )... );\n    }\n\n    bool Relogin( abort_callback& abort );\n    bool LoginWithUI( HWND hWnd );\n    void LogoutAndForget( abort_callback& abort );\n\n    std::string GetLoggedInUserName();\n\n    void RefreshBitrate();\n    void RefreshNormalization();\n    void RefreshPrivateMode();\n    void RefreshCacheSize();\n\nprivate:\n    void EventLoopThread();\n    void StartEventLoopThread();\n    void StopEventLoopThread();\n\n    std::optional<bool> WaitForLoginStatusUpdate( abort_callback& abort );\n\n    void RefreshPrivateModeNonBlocking();\n\n    // callbacks\n\n    void log_message( const char* error );\n    void logged_in( sp_error error );\n    void message_to_user( const char* error );\n    void notify_main_thread();\n    int music_delivery( const sp_audioformat* format, const void* frames, int num_frames );\n    void end_of_track();\n    void play_token_lost();\n    void connectionstate_updated();\n    void private_session_mode_changed( bool is_private );\n\nprivate:\n    AbortManager& abortManager_;\n\n    sp_session_callbacks callbacks_{};\n    sp_session_config config_{};\n\n    std::mutex decoderOwnerMutex_;\n    void* pDecoderOwner_ = nullptr;\n\n    std::mutex apiMutex_;\n    sp_session* pSpSession_ = nullptr;\n\n    std::unique_ptr<std::thread> pWorker_;\n    std::mutex workerMutex_;\n    std::condition_variable eventLoopCv_;\n    bool hasEvents_ = false;\n    bool shouldStopEventLoop_ = false;\n\n    std::mutex backendUsersMutex_;\n    std::unordered_set<LibSpotify_BackendUser*> backendUsers_;\n\n    enum class LoginStatus\n    {\n        uninitialized,\n        logged_in,\n        logged_out,\n        login_in_process,\n        logout_in_process,\n    };\n\n    std::mutex loginMutex_;\n    std::condition_variable loginCv_;\n    LoginStatus loginStatus_ = LoginStatus::uninitialized;\n    bool isLoginBad_ = false;\n\n    AudioBuffer audioBuffer_;\n};\n\n} // namespace sptf\n"
  },
  {
    "path": "foo_spotify/backend/libspotify_backend_user.h",
    "content": "#pragma once\n\nnamespace sptf\n{\n\nclass LibSpotify_BackendUser\n{\npublic:\n    ~LibSpotify_BackendUser() = default;\n    virtual void Finalize() = 0;\n};\n\n} // namespace sptf\n"
  },
  {
    "path": "foo_spotify/backend/libspotify_key.h",
    "content": "#pragma once\n\n#include <cstdint>\n\n// clang-format off\n\ninline constexpr uint8_t g_appkey[] = {\n\t0x01, 0xF8, 0x35, 0x9D, 0x45, 0x52, 0xD7, 0xA5, 0xC2, 0x91, 0xC0, 0x94, 0x18, 0x52, 0x81, 0x28,\n\t0x6A, 0xA4, 0xAE, 0x77, 0x4B, 0xE9, 0x87, 0xC9, 0x05, 0x2D, 0x72, 0x11, 0xC2, 0x59, 0x18, 0x6F,\n\t0xB3, 0x91, 0x4E, 0x63, 0xCE, 0x6E, 0xDA, 0xF5, 0xE3, 0xC7, 0xC6, 0xC9, 0x3B, 0x88, 0x37, 0x31,\n\t0x3C, 0xDA, 0x71, 0xF1, 0x4C, 0x68, 0x03, 0x1B, 0xF8, 0xC0, 0x4A, 0xBA, 0x20, 0x0B, 0xBE, 0xC4,\n\t0x2F, 0x49, 0x7A, 0xC5, 0x5C, 0xC4, 0x36, 0xF1, 0x94, 0xF7, 0xC6, 0x4F, 0x27, 0xFB, 0x5E, 0x31,\n\t0x00, 0x31, 0x53, 0x52, 0x74, 0x0B, 0x64, 0x16, 0x4B, 0x70, 0xA6, 0x71, 0x6D, 0xC0, 0x71, 0x7F,\n\t0x6B, 0xFD, 0xE5, 0xA4, 0x57, 0x99, 0x4A, 0x11, 0xB0, 0x0B, 0xBA, 0xC4, 0xF2, 0x9A, 0xB9, 0x33,\n\t0xC7, 0x5F, 0x70, 0x6D, 0x73, 0xEA, 0xAB, 0x88, 0xD2, 0x83, 0xAC, 0x33, 0xA7, 0xFE, 0xDA, 0xD7,\n\t0xF2, 0xAC, 0x04, 0x41, 0xAC, 0x7D, 0xEF, 0x88, 0x5A, 0x21, 0xEC, 0xD8, 0x02, 0x40, 0xB7, 0x0C,\n\t0x3A, 0x42, 0x2C, 0x26, 0x17, 0x9D, 0x82, 0x43, 0x50, 0x07, 0x1F, 0x2E, 0xAF, 0x72, 0x88, 0x65,\n\t0xDB, 0xA7, 0x83, 0xA6, 0x44, 0x06, 0x2E, 0x55, 0x08, 0xF2, 0x4C, 0x4A, 0x96, 0xF7, 0xD5, 0xFC,\n\t0x57, 0x75, 0x5F, 0x1C, 0x1D, 0xB1, 0x35, 0x5A, 0x48, 0x83, 0x1F, 0x60, 0x65, 0xBD, 0x40, 0xDD,\n\t0x03, 0x1D, 0x3A, 0x4E, 0xD6, 0xA8, 0xB8, 0x5E, 0xFC, 0x60, 0x59, 0xE0, 0xB3, 0xC5, 0x64, 0xD0,\n\t0x2A, 0x20, 0x48, 0x24, 0x5E, 0x9B, 0xE4, 0xF0, 0x45, 0xAA, 0x30, 0xCE, 0xB3, 0x11, 0x45, 0xB0,\n\t0x01, 0xDA, 0x82, 0x58, 0xFE, 0x4F, 0x97, 0xF2, 0x40, 0x4D, 0x8C, 0x83, 0x17, 0x8C, 0x97, 0xCF,\n\t0x40, 0x17, 0xDB, 0xC7, 0x19, 0xEC, 0xFA, 0x01, 0x4F, 0xE6, 0x78, 0x3A, 0x54, 0x3F, 0xE9, 0x62,\n\t0xA3, 0xF2, 0xDD, 0x0A, 0xDD, 0x90, 0xE4, 0x24, 0xE7, 0x57, 0x8C, 0x30, 0x18, 0x13, 0xA6, 0x9C,\n\t0x52, 0x7D, 0xBE, 0x0B, 0x10, 0xEA, 0x0C, 0x53, 0x87, 0x9B, 0x26, 0xBA, 0xA7, 0x70, 0xAE, 0x88,\n\t0x8A, 0xAA, 0x5E, 0x7C, 0x73, 0xC3, 0x08, 0x92, 0x29, 0xDC, 0xEA, 0x22, 0x25, 0x16, 0xB5, 0xF0,\n\t0x89, 0xF0, 0x88, 0xBE, 0xAB, 0x84, 0x6C, 0xFE, 0xF1, 0xBE, 0x8A, 0x81, 0x19, 0x0A, 0xE7, 0x64,\n\t0xC4,\n};\n\n// clang-format on\n"
  },
  {
    "path": "foo_spotify/backend/libspotify_wrapper.h",
    "content": "#pragma once\n\n#include <backend/libspotify_backend.h>\n\n#include <libspotify/api.h>\n\nnamespace sptf::wrapper\n{\n\nnamespace internal\n{\n\ntemplate <typename T>\nstruct SpotifyTraits\n{\n    static_assert( \"unknown specialization\" );\n};\n\ntemplate <>\nstruct SpotifyTraits<sp_track>\n{\n    static void AddRef( sp_track* album )\n    {\n        sp_track_add_ref( album );\n    }\n\n    static void Release( sp_track* album )\n    {\n        sp_track_release( album );\n    }\n\n    static bool IsLoaded( sp_track* album )\n    {\n        return sp_track_is_loaded( album );\n    }\n};\n\ntemplate <>\nstruct SpotifyTraits<sp_link>\n{\n    static void AddRef( sp_link* link )\n    {\n        sp_link_add_ref( link );\n    }\n\n    static void Release( sp_link* link )\n    {\n        sp_link_release( link );\n    }\n\n    // does not have a \"IsLoaded\" method\n};\n\n} // namespace internal\n\ntemplate <typename T>\nclass Ptr\n{\npublic:\n    Ptr() = default;\n\n    Ptr( T* ptr )\n        : ptr_( ptr )\n    {\n\n        if ( ptr_ )\n        {\n            internal::SpotifyTraits<T>::AddRef( ptr_ );\n        }\n    }\n\n    Ptr( const Ptr<T*>& other )\n        : ptr_( other.ptr_ )\n    {\n        if ( ptr_ )\n        {\n            internal::SpotifyTraits<T>::AddRef( ptr_ );\n        }\n    }\n\n    Ptr( Ptr<T*>&& other )\n        : ptr_( other.ptr_ )\n    {\n        other.ptr_ = nullptr;\n    }\n\n    void Release()\n    {\n        auto ptr = ptr_;\n        ptr_ = nullptr;\n        if ( ptr )\n        {\n            internal::SpotifyTraits<T>::Release( ptr );\n        }\n    }\n\n    void Attach( T* ptr )\n    {\n        if ( ptr_ )\n        {\n            internal::SpotifyTraits<T>::Release( ptr );\n        }\n        ptr_ = ptr;\n    }\n\n    operator bool() const\n    {\n        return !!ptr_;\n    }\n\n    bool operator!() const\n    {\n        return !ptr_;\n    }\n\n    T* operator=( T* ptr )\n    {\n        Release();\n        ptr_ = ptr;\n        if ( ptr_ )\n        {\n            internal::SpotifyTraits<T>::AddRef( ptr_ );\n        }\n        return ptr_;\n    }\n\n    operator T*() const\n    {\n        return ptr_;\n    }\n\nprivate:\n    T* ptr_ = nullptr;\n};\n\n} // namespace sptf::wrapper\n"
  },
  {
    "path": "foo_spotify/backend/spotify_instance.cpp",
    "content": "#include <stdafx.h>\n\n#include \"spotify_instance.h\"\n\n#include <backend/libspotify_backend.h>\n#include <backend/webapi_auth.h>\n#include <backend/webapi_backend.h>\n#include <fb2k/playback.h>\n#include <utils/abort_manager.h>\n\n#include <qwr/abort_callback.h>\n#include <qwr/thread_pool.h>\n\nnamespace sptf\n{\n\nSpotifyInstance& SpotifyInstance::Get()\n{\n    static SpotifyInstance si;\n    return si;\n}\n\nvoid SpotifyInstance::Finalize()\n{\n    std::lock_guard lg( mutex_ );\n    isFinalized_ = true;\n\n    const auto finalize = []( auto& pElem ) {\n        if ( pElem )\n        {\n            try\n            {\n                pElem->Finalize();\n            }\n            catch ( const std::exception& )\n            {\n            }\n            pElem.reset();\n        }\n    };\n\n    if ( fb2k_playCallbacks_initialized_ )\n    {\n        fb2k::PlayCallbacks::Finalize();\n        fb2k_playCallbacks_initialized_ = false;\n    }\n\n    finalize( pWebApi_backend_ );\n    finalize( pLibSpotify_backend_ );\n    finalize( pAbortManager_ );\n    finalize( pThreadPool_ );\n}\n\nqwr::ThreadPool& SpotifyInstance::GetThreadPool()\n{\n    InitializeAll();\n    assert( pThreadPool_ );\n    return *pThreadPool_;\n}\n\nAbortManager& SpotifyInstance::GetAbortManager()\n{\n    InitializeAll();\n    assert( pAbortManager_ );\n    return *pAbortManager_;\n}\n\nLibSpotify_Backend& SpotifyInstance::GetLibSpotify_Backend()\n{\n    InitializeAll();\n    assert( pLibSpotify_backend_ );\n    return *pLibSpotify_backend_;\n}\n\nWebApi_Backend& SpotifyInstance::GetWebApi_Backend()\n{\n    InitializeAll();\n    assert( pWebApi_backend_ );\n    return *pWebApi_backend_;\n}\n\nvoid SpotifyInstance::InitializeAll()\n{\n    std::lock_guard lg( mutex_ );\n    if ( isFinalized_ )\n    {\n        throw qwr::QwrException( \"foobar2000 is exiting\" );\n    }\n\n    if ( !pThreadPool_ )\n    {\n        pThreadPool_ = std::make_unique<qwr::ThreadPool>( \"SPTF Worker\", 2 );\n    }\n    if ( !pAbortManager_ )\n    {\n        pAbortManager_ = std::make_unique<AbortManager>();\n    }\n    if ( !pLibSpotify_backend_ )\n    {\n        pLibSpotify_backend_ = std::make_unique<LibSpotify_Backend>( *pAbortManager_ );\n    }\n    if ( !pWebApi_backend_ )\n    {\n        pWebApi_backend_ = std::make_unique<WebApi_Backend>( *pAbortManager_ );\n    }\n    if ( !fb2k_playCallbacks_initialized_ )\n    {\n        fb2k::PlayCallbacks::Initialize( *pLibSpotify_backend_ );\n        fb2k_playCallbacks_initialized_ = true;\n    }\n}\n\n} // namespace sptf"
  },
  {
    "path": "foo_spotify/backend/spotify_instance.h",
    "content": "#pragma once\n\n#include <mutex>\n\nnamespace qwr\n{\nclass ThreadPool;\n}\n\nnamespace sptf\n{\n\nclass AbortManager;\nclass LibSpotify_Backend;\nclass WebApi_Backend;\n\nnamespace fb2k\n{\n\nclass PlayCallbacks;\n\n}\n\nclass SpotifyInstance\n{\n\npublic:\n    ~SpotifyInstance() = default;\n\n    static SpotifyInstance& Get();\n    void Finalize();\n\n    qwr::ThreadPool& GetThreadPool();\n    AbortManager& GetAbortManager();\n    LibSpotify_Backend& GetLibSpotify_Backend();\n    WebApi_Backend& GetWebApi_Backend();\n\nprivate:\n    SpotifyInstance() = default;\n    void InitializeAll();\n\nprivate:\n    std::mutex mutex_;\n    bool isFinalized_ = false;\n\n    std::unique_ptr<qwr::ThreadPool> pThreadPool_;\n    std::unique_ptr<AbortManager> pAbortManager_;\n    std::unique_ptr<LibSpotify_Backend> pLibSpotify_backend_;\n    std::unique_ptr<WebApi_Backend> pWebApi_backend_;\n    bool fb2k_playCallbacks_initialized_ = false;\n};\n\n} // namespace sptf"
  },
  {
    "path": "foo_spotify/backend/spotify_object.cpp",
    "content": "#include <stdafx.h>\n\n#include \"spotify_object.h\"\n\n#include <qwr/string_helpers.h>\n\nusing namespace std::literals::string_view_literals;\n\nnamespace sptf\n{\n\nbool SpotifyObject::IsValid( std::string_view input )\n{\n    try\n    {\n        SpotifyObject tmp( input );\n        (void)tmp;\n        return true;\n    }\n    catch ( const qwr::QwrException& )\n    {\n        return false;\n    }\n}\n\nSpotifyObject::SpotifyObject( std::string_view input )\n{\n    const auto schemaPrefix = \"sptf://\"sv;\n    if ( input._Starts_with( schemaPrefix ) )\n    {\n        input.remove_prefix( schemaPrefix.size() );\n    }\n\n    const auto urlPrefix = \"https://open.spotify.com/\"sv;\n    if ( input._Starts_with( urlPrefix ) )\n    {\n        input.remove_prefix( urlPrefix.size() );\n\n        const auto ret = qwr::string::Split( input, '/' );\n        qwr::QwrException::ExpectTrue( ret.size() == 2, \"Invalid URL\" );\n\n        const auto localType = ret[0];\n        type = std::string( localType.data(), localType.size() );\n\n        const auto localId = [localId = ret[1]] {\n            const auto pos = localId.find( '?' );\n            if ( pos == std::string_view::npos )\n            {\n                return localId;\n            }\n\n            return localId.substr( 0, pos );\n        }();\n        qwr::QwrException::ExpectTrue( !localId.empty(), \"Invalid Spotify object id: {}\", localId );\n        id = std::string( localId.cbegin(), localId.cend() );\n    }\n    else\n    {\n        const auto ret = qwr::string::Split( input, ':' );\n        qwr::QwrException::ExpectTrue( ret.size() == 3, \"Invalid URI\" );\n        qwr::QwrException::ExpectTrue( ret[0] == \"spotify\"sv, \"Invalid URI\" );\n\n        const auto localType = ret[1];\n        type = std::string( localType.data(), localType.size() );\n\n        const auto localId = ret[2];\n        qwr::QwrException::ExpectTrue( !localId.empty(), \"Invalid Spotify object id: {}\", localId );\n        id = std::string( localId.cbegin(), localId.cend() );\n    }\n}\n\nSpotifyObject::SpotifyObject( std::string_view type, std::string_view id )\n    : type( type )\n    , id( id )\n{\n}\n\nstd::string SpotifyObject::ToUri() const\n{\n    return fmt::format( \"spotify:{}:{}\", type, id );\n}\n\nstd::string SpotifyObject::ToUrl() const\n{\n    return fmt::format( \"https://open.spotify.com/{}/{}\", type, id );\n}\n\nstd::string SpotifyObject::ToSchema() const\n{\n    return fmt::format( \"sptf://spotify:{}:{}\", type, id );\n}\n\nSpotifyFilteredTrack::SpotifyFilteredTrack( std::string_view id )\n    : object_( \"track\", id )\n{\n}\n\nSpotifyFilteredTrack SpotifyFilteredTrack::Parse( std::string_view input )\n{\n    if ( !IsValid( input, false ) )\n    {\n        throw qwr::QwrException( \"Unsupported input format: {}\", input );\n    }\n\n    SpotifyObject so( input );\n    assert( so.type == \"track\" );\n\n    return SpotifyFilteredTrack( so.id );\n}\n\nconst std::string& SpotifyFilteredTrack::Id() const\n{\n    return object_.id;\n}\n\nstd::string SpotifyFilteredTrack::ToUri() const\n{\n    return object_.ToUri();\n}\n\nstd::string SpotifyFilteredTrack::ToUrl() const\n{\n    return object_.ToUrl();\n}\n\nstd::string SpotifyFilteredTrack::ToSchema() const\n{\n    return object_.ToSchema();\n}\n\nbool SpotifyFilteredTrack::IsValid( std::string_view input, bool usePurePathOnly )\n{\n    const auto schemaPrefix = \"sptf://\"sv;\n    if ( input._Starts_with( schemaPrefix ) )\n    {\n        input.remove_prefix( schemaPrefix.size() );\n    }\n    else if ( usePurePathOnly )\n    {\n        return false;\n    }\n\n    return input._Starts_with( \"spotify:track:\"sv );\n}\n\n} // namespace sptf\n"
  },
  {
    "path": "foo_spotify/backend/spotify_object.h",
    "content": "#pragma once\n\n#include <string>\n\nnamespace sptf\n{\n\nstruct SpotifyObject\n{\n    /// @throw qwr::QwrException\n    SpotifyObject( std::string_view input );\n    /// @throw qwr::QwrException\n    SpotifyObject( std::string_view type, std::string_view id );\n\n    std::string ToUri() const;\n    std::string ToUrl() const;\n    std::string ToSchema() const;\n\n    static bool IsValid( std::string_view input );\n\n    std::string type;\n    std::string id;\n};\n\nclass SpotifyFilteredTrack\n{\npublic:\n    /// @throw qwr::QwrException\n    SpotifyFilteredTrack( std::string_view id );\n    /// @throw qwr::QwrException\n    static SpotifyFilteredTrack Parse( std::string_view input );\n\n    const std::string& Id() const;\n    std::string ToUri() const;\n    std::string ToUrl() const;\n    std::string ToSchema() const;\n\n    static bool IsValid( std::string_view input, bool usePurePathOnly );\n\nprivate:\n    SpotifyObject object_;\n};\n\n} // namespace sptf\n"
  },
  {
    "path": "foo_spotify/backend/webapi_auth.cpp",
    "content": "#include <stdafx.h>\n\n#include \"webapi_auth.h\"\n\n#include <backend/spotify_instance.h>\n#include <backend/webapi_auth_scopes.h>\n#include <ui/ui_not_auth.h>\n#include <utils/abort_manager.h>\n#include <utils/json_std_extenders.h>\n\n#include <bcrypt.h>\n#include <component_urls.h>\n#include <pplawait.h>\n#include <winternl.h>\n\n#include <cpprest/asyncrt_utils.h>\n#include <cpprest/http_client.h>\n#include <cpprest/http_listener.h>\n#include <cpprest/json.h>\n#include <cpprest/uri_builder.h>\n#include <nonstd/span.hpp>\n#include <qwr/file_helpers.h>\n#include <qwr/final_action.h>\n#include <qwr/string_helpers.h>\n\n#include <random>\n#include <string_view>\n#include <unordered_set>\n\n#include <experimental/resumable>\n\n// TODO: move to props\n#pragma comment( lib, \"bcrypt.lib\" )\n#pragma comment( lib, \"Crypt32.lib\" )\n#pragma comment( lib, \"winhttp.lib\" )\n#pragma comment( lib, \"httpapi.lib\" )\n\n// TODO: add abortable to cts\n// TODO: clean up mutex handling - it's a mess here\n\nnamespace fs = std::filesystem;\n\nusing namespace sptf;\n\nnamespace\n{\n\nconstexpr wchar_t k_clientId[] = L\"30826243a65f43f19b038fd65ffaa8b5\";\n\n} // namespace\n\nnamespace\n{\n\nstd::wstring GenerateCodeVerifier()\n{\n    static constexpr wchar_t codeVerifierChars[] =\n        L\"abcdefghijklmnopqrstuvwxyz\"\n        L\"ABCDEFGHIJKLMNOPQRSTUVWXYZ\"\n        L\"1234567890\"\n        L\"_.-~\";\n\n    std::random_device rd;\n    const auto size = std::uniform_int_distribution<size_t>( 43, 128 )( rd );\n\n    std::wstring ret;\n    ret.resize( size );\n\n    std::uniform_int_distribution<size_t> charDist( 0, std::size( codeVerifierChars ) - 2 );\n    for ( auto& ch: ret )\n    {\n        ch = codeVerifierChars[charDist( rd )];\n    }\n\n    return ret;\n}\n\nstd::vector<uint8_t> Sha256Hash( nonstd::span<const uint8_t> data )\n{\n    // TODO: cleanup add error handling\n\n    NTSTATUS status;\n    BCRYPT_ALG_HANDLE alg_handle = nullptr;\n    BCRYPT_HASH_HANDLE hash_handle = nullptr;\n\n    std::vector<uint8_t> hash;\n    DWORD hash_len = 0;\n    ULONG result_len = 0;\n\n    status = BCryptOpenAlgorithmProvider( &alg_handle, BCRYPT_SHA256_ALGORITHM, nullptr, 0 );\n    if ( !NT_SUCCESS( status ) )\n    {\n        goto cleanup;\n    }\n    status = BCryptGetProperty( alg_handle, BCRYPT_HASH_LENGTH, (PBYTE)&hash_len, sizeof( hash_len ), &result_len, 0 );\n    if ( !NT_SUCCESS( status ) )\n    {\n        goto cleanup;\n    }\n    hash.resize( hash_len );\n\n    status = BCryptCreateHash( alg_handle, &hash_handle, nullptr, 0, nullptr, 0, 0 );\n    if ( !NT_SUCCESS( status ) )\n    {\n        goto cleanup;\n    }\n    status = BCryptHashData( hash_handle, (PBYTE)data.data(), (ULONG)data.size(), 0 );\n    if ( !NT_SUCCESS( status ) )\n    {\n        goto cleanup;\n    }\n    status = BCryptFinishHash( hash_handle, hash.data(), hash_len, 0 );\n    if ( !NT_SUCCESS( status ) )\n    {\n        goto cleanup;\n    }\n\ncleanup:\n    if ( hash_handle )\n    {\n        BCryptDestroyHash( hash_handle );\n    }\n    if ( alg_handle )\n    {\n        BCryptCloseAlgorithmProvider( alg_handle, 0 );\n    }\n\n    return hash;\n}\n\nstd::wstring GenerateChallengeCode( const std::wstring& codeVerifier )\n{\n    const auto code_u8 = qwr::unicode::ToU8( codeVerifier );\n    const auto hash = Sha256Hash( nonstd::span<const uint8_t>( reinterpret_cast<const uint8_t*>( code_u8.data() ), code_u8.size() ) );\n    auto base64 = utility::conversions::to_base64( hash );\n    {\n        while ( base64[base64.size() - 1] == L'=' )\n        {\n            base64.resize( base64.size() - 1 );\n        }\n        for ( auto& ch: base64 )\n        {\n            switch ( ch )\n            {\n            case L'+':\n            {\n                ch = L'-';\n                break;\n            }\n            case L'/':\n            {\n                ch = L'_';\n                break;\n            }\n            default:\n            {\n                break;\n            }\n            }\n        }\n    }\n\n    return base64;\n}\n\nvoid OpenAuthConfirmationInBrowser( const std::wstring& url )\n{\n    ShellExecuteW( nullptr, L\"open\", url.c_str(), nullptr, nullptr, SW_SHOWNORMAL );\n}\n\n} // namespace\n\nnamespace sptf\n{\n\nstruct AuthData\n{\n    std::wstring accessToken;\n    std::wstring refreshToken;\n    std::chrono::time_point<std::chrono::system_clock> expiresAt = std::chrono::system_clock::now();\n    WebApiAuthScopes scopes;\n};\n\nvoid to_json( nlohmann::json& j, const AuthData& p )\n{\n    j[\"access_token\"] = p.accessToken;\n    j[\"refresh_token\"] = p.refreshToken;\n    j[\"expires_at\"] = std::chrono::time_point_cast<std::chrono::minutes>( p.expiresAt ).time_since_epoch().count();\n    j[\"scopes\"] = p.scopes;\n}\n\nvoid from_json( const nlohmann::json& j, AuthData& p )\n{\n    j.at( \"access_token\" ).get_to( p.accessToken );\n    j.at( \"refresh_token\" ).get_to( p.refreshToken );\n    p.expiresAt = std::chrono::time_point<std::chrono::system_clock>( std::chrono::minutes( j.at( \"expires_at\" ).get<int>() ) );\n    if ( j.contains( \"scopes\" ) )\n    {\n        j[\"scopes\"].get_to( p.scopes );\n    }\n    else\n    { // for backwards compatibility\n        WebApiAuthScopes scopes;\n        scopes.playlist_read_collaborative = true;\n        scopes.playlist_read_private = true;\n        p.scopes = scopes;\n    }\n}\n\nWebApiAuthorizer::WebApiAuthorizer( const web::http::client::http_client_config& config, AbortManager& abortManager )\n    : abortManager_( abortManager )\n    , client_( url::accountsApi, config )\n{\n    const auto authpath = path::WebApiSettings() / \"auth.json\";\n    if ( fs::exists( authpath ) )\n    {\n        try\n        {\n            const auto data = qwr::file::ReadFileW( authpath, CP_UTF8, false );\n            const auto dataJson = nlohmann::json::parse( data );\n            dataJson.get_to( pAuthData_ );\n        }\n        catch ( const std::exception& )\n        {\n            pAuthData_.reset();\n            try\n            {\n                fs::remove( authpath );\n            }\n            catch ( const fs::filesystem_error& )\n            {\n            }\n        }\n    }\n}\n\nWebApiAuthorizer::~WebApiAuthorizer()\n{\n    cts_.cancel();\n    StopResponseListener();\n}\n\nbool WebApiAuthorizer::HasRefreshToken() const\n{\n    std::lock_guard lock( accessTokenMutex_ );\n    return !!pAuthData_;\n}\n\nconst std::wstring WebApiAuthorizer::GetAccessToken( abort_callback& abort )\n{\n    std::lock_guard lock( accessTokenMutex_ );\n\n    if ( !pAuthData_ )\n    {\n        ::fb2k::inMainThread( [&] {\n            playback_control::get()->stop();\n            ui::NotAuthHandler::Get().ShowDialog();\n        } );\n        throw qwr::QwrException( \"Failed to get authenticated Spotify session\" );\n    }\n\n    UpdateRefreshToken_NonBlocking( abort );\n\n    assert( !pAuthData_->accessToken.empty() );\n    return pAuthData_->accessToken;\n}\n\nvoid WebApiAuthorizer::ClearAuth()\n{\n    pAuthData_.reset();\n    codeVerifier_.clear();\n    state_.clear();\n\n    const auto authpath = path::WebApiSettings() / \"auth.json\";\n    if ( fs::exists( authpath ) )\n    {\n        fs::remove( authpath );\n    }\n}\n\nvoid WebApiAuthorizer::CancelAuth()\n{\n    // TODO: rethink cts handling: current scheme is not thread-safe.\n    // Example: CancelAuth from preferences (and reassign cts_), while some other thread is using cts_.\n    cts_.cancel();\n    cts_ = pplx::cancellation_token_source();\n    StopResponseListener();\n    ClearAuth();\n}\n\nvoid WebApiAuthorizer::AuthenticateClean( const WebApiAuthScopes& scopes, std::function<void()> onResponseEnd )\n{\n    assert( core_api::is_main_thread() );\n\n    StopResponseListener();\n    StartResponseListener( onResponseEnd );\n\n    // <https://developer.spotify.com/documentation/general/guides/authorization-guide/#authorization-code-flow-with-proof-key-for-code-exchange-pkce>\n\n    codeVerifier_ = GenerateCodeVerifier();\n\n    web::uri_builder builder( url::accountsAuthenticate );\n    builder\n        .append_query( L\"client_id\", web::uri::encode_data_string( k_clientId ), false )\n        .append_query( L\"response_type\", L\"code\" )\n        .append_query( L\"redirect_uri\", web::uri::encode_data_string( url::redirectUri ), false )\n        .append_query( L\"code_challenge_method\", L\"S256\" )\n        .append_query( L\"code_challenge\", GenerateChallengeCode( codeVerifier_ ) )\n        .append_query( L\"scope\", web::uri::encode_data_string( scopes.ToWebString() ), false );\n    // TODO: cookie?\n    // builder.append_query( L\"state\", L\"azaza\" );\n\n    OpenAuthConfirmationInBrowser( builder.to_string() );\n}\n\nvoid WebApiAuthorizer::AuthenticateClean_Cleanup()\n{\n    StopResponseListener();\n}\n\nvoid WebApiAuthorizer::UpdateRefreshToken( abort_callback& abort )\n{\n    std::lock_guard lock( accessTokenMutex_ );\n    UpdateRefreshToken_NonBlocking( abort );\n}\n\nvoid WebApiAuthorizer::UpdateRefreshToken_NonBlocking( abort_callback& abort )\n{\n    assert( pAuthData_ );\n\n    if ( std::chrono::system_clock::now() + std::chrono::minutes( 1 ) < pAuthData_->expiresAt )\n    {\n        return;\n    }\n\n    web::uri_builder builder;\n    builder\n        .append_query( L\"grant_type\", L\"refresh_token\" )\n        .append_query( L\"refresh_token\", pAuthData_->refreshToken )\n        .append_query( L\"client_id\", web::uri::encode_data_string( k_clientId ), false );\n\n    web::http::http_request req( web::http::methods::POST );\n    req.headers().set_content_type( L\"application/x-www-form-urlencoded\" );\n    req.set_request_uri( builder.to_uri() );\n\n    auto ctsToken = cts_.get_token();\n    auto localCts = Concurrency::cancellation_token_source::create_linked_source( ctsToken );\n    const auto abortableScope = abortManager_.GetAbortableScope( [&localCts] { localCts.cancel(); }, abort );\n\n    auto response = client_.request( req, cts_.get_token() );\n    HandleAuthenticationResponse( response.get() );\n}\n\npplx::task<void> WebApiAuthorizer::CompleteAuthentication( const std::wstring& responseUrl )\n{\n    // TODO: final_action\n    web::uri uri( responseUrl );\n    // TODO: check redirectUri?\n\n    const auto data = web::uri::split_query( uri.query() );\n\n    if ( data.count( L\"error\" ) )\n    {\n        throw qwr::QwrException( qwr::unicode::ToU8( fmt::format( L\"Authentication failed: {}\", data.at( L\"error\" ) ) ) );\n    }\n\n    if ( !state_.empty() && ( !data.count( L\"state\" ) || data.at( L\"state\" ) != state_ ) )\n    {\n        throw qwr::QwrException( \"Malformed authentication response: `state` mismatch\" );\n    }\n\n    qwr::QwrException::ExpectTrue( data.count( L\"code\" ), L\"Malformed authentication response: missing `code`\" );\n\n    web::uri_builder builder;\n    builder\n        .append_query( L\"client_id\", k_clientId )\n        .append_query( L\"grant_type\", L\"authorization_code\" )\n        .append_query( L\"code\", data.at( L\"code\" ) )\n        .append_query( L\"redirect_uri\", web::uri::encode_data_string( url::redirectUri ), false )\n        .append_query( L\"code_verifier\", codeVerifier_, false );\n\n    web::http::http_request req( web::http::methods::POST );\n    req.headers().set_content_type( L\"application/x-www-form-urlencoded\" );\n    req.set_body( builder.query() );\n\n    const auto response = co_await client_.request( req, cts_.get_token() );\n    HandleAuthenticationResponse( response );\n}\n\nvoid WebApiAuthorizer::StartResponseListener( std::function<void()> onResponseEnd )\n{\n    assert( !pListener_ );\n    pListener_ = std::make_unique<web::http::experimental::listener::http_listener>( url::redirectUri );\n    pListener_->support( [this, onResponseEnd]( const auto& request ) {\n        try\n        {\n            if ( request.request_uri().path() == L\"/\" && request.request_uri().query() != L\"\" )\n            {\n                const auto callbackCaller = qwr::final_action( [&] { onResponseEnd(); } );\n                try\n                {\n                    CompleteAuthentication( request.request_uri().to_string() ).wait();\n\n                    web::http::http_response res;\n                    res.set_status_code( web::http::status_codes::OK );\n                    res.headers().set_content_type( L\"text/html; charset=utf-8\" );\n                    res.set_body(\n                        L\"<html>\\n\"\n                        L\"<head>\\n\"\n                        L\"</head>\\n\"\n                        L\"<body onload=\\\" waitFiveSec() \\\">\\n\"\n                        L\"<p><b>foo_spotify</b> was successfully authenticated!</p>\\n \"\n                        L\"<p>You can close this tab now :)</p>\\n \"\n                        L\"</body>\\n\"\n                        L\"</html>\" );\n\n                    request.reply( res ).wait();\n                }\n                catch ( const std::exception& e )\n                {\n                    pAuthData_.reset();\n                    auto errorMsg = qwr::unicode::ToWide( std::string( e.what() ) );\n                    {\n                        size_t pos = 0;\n                        while ( ( pos = errorMsg.find( L\"\\n\", pos ) ) != std::string::npos )\n                        {\n                            errorMsg.replace( pos, 1, L\"<br>\" );\n                            pos += 4;\n                        }\n                    }\n\n                    web::http::http_response res;\n                    res.set_status_code( web::http::status_codes::OK );\n                    res.headers().set_content_type( L\"text/html; charset=utf-8\" );\n                    res.set_body(\n                        L\"<html>\\n\"\n                        L\"<head>\\n\"\n                        L\"</head>\\n\"\n                        L\"<p><b>foo_spotify</b> failed to authenticate!</p>\\n\"\n                        L\"<p>Error:</p>\\n\"\n                        L\"<p>\"\n                        + errorMsg + \"</p>\\n\"\n                                     L\"</body>\\n\"\n                                     L\"</html>\" );\n\n                    request.reply( res ).wait();\n                }\n            }\n            else\n            {\n                web::http::http_response res;\n                res.set_status_code( web::http::status_codes::OK );\n                res.headers().set_content_type( L\"text/html; charset=utf-8\" );\n                res.set_body( L\"<html><body><p>Congratulations! You found a useless page! o/</p></body></html>\" );\n\n                request.reply( res ).wait();\n            }\n        }\n        catch ( ... )\n        {\n        }\n    } );\n    pListener_->open().wait();\n}\n\nvoid WebApiAuthorizer::StopResponseListener()\n{\n    if ( pListener_ )\n    {\n        pListener_->close().wait();\n        pListener_.reset();\n    }\n}\n\nvoid WebApiAuthorizer::HandleAuthenticationResponse( const web::http::http_response& response )\n{\n    if ( response.status_code() != 200 )\n    {\n        ClearAuth();\n\n        throw qwr::QwrException( L\"{}: {}\\n\"\n                                 L\"Additional data: {}\\n\",\n                                 (int)response.status_code(),\n                                 response.reason_phrase(),\n                                 [&]() -> std::wstring {\n                                     try\n                                     {\n                                         const auto responseJson = nlohmann::json::parse( response.extract_string().get() );\n                                         return qwr::unicode::ToWide( responseJson.dump( 2 ) );\n                                     }\n                                     catch ( ... )\n                                     {\n                                         return response.to_string();\n                                     }\n                                 }() );\n    }\n\n    const auto responseJson = response.extract_json().get();\n    qwr::QwrException::ExpectTrue( responseJson.is_object(),\n                                   L\"Malformed authentication response: json is not an object\" );\n\n    qwr::QwrException::ExpectTrue( responseJson.at( L\"token_type\" ).as_string() == L\"Bearer\",\n                                   L\"Malformed authentication response: invalid `token_type`: {}\",\n                                   responseJson.at( L\"token_type\" ).as_string() );\n\n    auto pAuthData = std::make_unique<AuthData>();\n    pAuthData->accessToken = responseJson.at( L\"access_token\" ).as_string();\n    pAuthData->refreshToken = responseJson.at( L\"refresh_token\" ).as_string();\n    pAuthData->expiresAt = std::chrono::system_clock::now() + std::chrono::seconds( responseJson.at( L\"expires_in\" ).as_integer() );\n\n    auto scopesSplit = qwr::string::Split<wchar_t>( responseJson.at( L\"scope\" ).as_string(), L' ' );\n    pAuthData->scopes = WebApiAuthScopes( scopesSplit );\n\n    const auto settingsPath = path::WebApiSettings();\n    if ( !fs::exists( settingsPath ) )\n    {\n        fs::create_directories( settingsPath );\n    }\n    // not using component config because it's not saved immediately\n    qwr::file::WriteFile( settingsPath / \"auth.json\", nlohmann::json( pAuthData ).dump( 2 ) );\n\n    pAuthData_ = std::move( pAuthData );\n}\n\n} // namespace sptf\n"
  },
  {
    "path": "foo_spotify/backend/webapi_auth.h",
    "content": "#pragma once\n\n#include <cpprest/asyncrt_utils.h>\n#include <cpprest/http_client.h>\n#include <cpprest/http_msg.h>\n\n#include <chrono>\n\nnamespace web::http::experimental::listener\n{\nclass http_listener;\n}\n\nnamespace sptf\n{\n\nclass AbortManager;\nstruct WebApiAuthScopes;\nstruct AuthData;\n\nclass WebApiAuthorizer\n{\npublic:\n    WebApiAuthorizer( const web::http::client::http_client_config& config, AbortManager& abortManager );\n    ~WebApiAuthorizer();\n\n    bool HasRefreshToken() const;\n\n    const std::wstring GetAccessToken( abort_callback& abort );\n\n    void ClearAuth();\n    void CancelAuth();\n\n    void AuthenticateClean( const WebApiAuthScopes& scopes, std::function<void()> onResponseEnd );\n    void AuthenticateClean_Cleanup();\n    void UpdateRefreshToken( abort_callback& abort );\n\nprivate:\n    void UpdateRefreshToken_NonBlocking( abort_callback& abort );\n    pplx::task<void> CompleteAuthentication( const std::wstring& respondUrl );\n\n    void StartResponseListener( std::function<void()> onResponseEnd );\n    void StopResponseListener();\n    void HandleAuthenticationResponse( const web::http::http_response& response );\n\nprivate:\n    AbortManager& abortManager_;\n\n    pplx::cancellation_token_source cts_;\n    web::http::client::http_client client_;\n    std::unique_ptr<web::http::experimental::listener::http_listener> pListener_;\n\n    std::wstring codeVerifier_;\n    std::wstring state_;\n\n    mutable std::mutex accessTokenMutex_;\n    std::unique_ptr<AuthData> pAuthData_;\n};\n\n} // namespace sptf"
  },
  {
    "path": "foo_spotify/backend/webapi_auth_scopes.cpp",
    "content": "#include <stdafx.h>\n\n#include \"webapi_auth_scopes.h\"\n\n#include <unordered_set>\n\nusing namespace std::literals::string_view_literals;\n\nnamespace sptf\n{\n\nWebApiAuthScopes::WebApiAuthScopes( nonstd::span<const std::wstring_view> scopes )\n{\n    std::unordered_set<std::wstring_view> scopeSet( scopes.cbegin(), scopes.cend() );\n\n#define SPTF_FILL_SCOPE( scope_var, scope_id ) \\\n    if ( scopeSet.count( scope_id ) )          \\\n    {                                          \\\n        scope_var = true;                      \\\n    }\n\n    SPTF_FILL_SCOPE( playlist_modify_public, L\"playlist-modify-public\"sv )\n    SPTF_FILL_SCOPE( playlist_read_private, L\"playlist-read-private\"sv )\n    SPTF_FILL_SCOPE( playlist_modify_private, L\"playlist-modify-private\"sv )\n    SPTF_FILL_SCOPE( playlist_read_collaborative, L\"playlist-read-collaborative\"sv )\n    SPTF_FILL_SCOPE( user_read_playback_position, L\"user-read-playback-position\"sv )\n    SPTF_FILL_SCOPE( user_read_recently_played, L\"user-read-recently-played\"sv )\n    SPTF_FILL_SCOPE( user_top_read, L\"user-top-read\"sv )\n    SPTF_FILL_SCOPE( user_follow_modify, L\"user-follow-modify\"sv )\n    SPTF_FILL_SCOPE( user_follow_read, L\"user-follow-read\"sv )\n    SPTF_FILL_SCOPE( user_library_read, L\"user-library-read\"sv )\n    SPTF_FILL_SCOPE( user_library_modify, L\"user-library-modify\"sv )\n    SPTF_FILL_SCOPE( user_read_private, L\"user-read-private\"sv )\n    SPTF_FILL_SCOPE( user_read_email, L\"user-read-email\"sv )\n\n#undef SPTF_FILL_SCOPE\n}\n\nstd::wstring WebApiAuthScopes::ToWebString() const\n{\n    std::wstring ret;\n\n#define SPTF_FILL_SCOPE( scope_var, scope_id ) \\\n    if ( scope_var )                           \\\n    {                                          \\\n        ret += scope_id;                       \\\n        ret += L\" \";                           \\\n    }\n\n    SPTF_FILL_SCOPE( playlist_modify_public, L\"playlist-modify-public\"sv )\n    SPTF_FILL_SCOPE( playlist_read_private, L\"playlist-read-private\"sv )\n    SPTF_FILL_SCOPE( playlist_modify_private, L\"playlist-modify-private\"sv )\n    SPTF_FILL_SCOPE( playlist_read_collaborative, L\"playlist-read-collaborative\"sv )\n    SPTF_FILL_SCOPE( user_read_playback_position, L\"user-read-playback-position\"sv )\n    SPTF_FILL_SCOPE( user_read_recently_played, L\"user-read-recently-played\"sv )\n    SPTF_FILL_SCOPE( user_top_read, L\"user-top-read\"sv )\n    SPTF_FILL_SCOPE( user_follow_modify, L\"user-follow-modify\"sv )\n    SPTF_FILL_SCOPE( user_follow_read, L\"user-follow-read\"sv )\n    SPTF_FILL_SCOPE( user_library_read, L\"user-library-read\"sv )\n    SPTF_FILL_SCOPE( user_library_modify, L\"user-library-modify\"sv )\n    SPTF_FILL_SCOPE( user_read_private, L\"user-read-private\"sv )\n    SPTF_FILL_SCOPE( user_read_email, L\"user-read-email\"sv )\n\n#undef SPTF_FILL_SCOPE\n\n    return ret;\n}\n\nvoid to_json( nlohmann::json& j, const WebApiAuthScopes& p )\n{\n#define SPTF_FILL_SCOPE( scope_var ) \\\n    if ( p.scope_var )               \\\n    {                                \\\n        j[#scope_var] = p.scope_var; \\\n    }\n\n    SPTF_FILL_SCOPE( playlist_modify_public )\n    SPTF_FILL_SCOPE( playlist_read_private )\n    SPTF_FILL_SCOPE( playlist_modify_private )\n    SPTF_FILL_SCOPE( playlist_read_collaborative )\n    SPTF_FILL_SCOPE( user_read_playback_position )\n    SPTF_FILL_SCOPE( user_read_recently_played )\n    SPTF_FILL_SCOPE( user_top_read )\n    SPTF_FILL_SCOPE( user_follow_modify )\n    SPTF_FILL_SCOPE( user_follow_read )\n    SPTF_FILL_SCOPE( user_library_read )\n    SPTF_FILL_SCOPE( user_library_modify )\n    SPTF_FILL_SCOPE( user_read_private )\n    SPTF_FILL_SCOPE( user_read_email )\n\n#undef SPTF_FILL_SCOPE\n}\n\nvoid from_json( const nlohmann::json& j, WebApiAuthScopes& p )\n{\n#define SPTF_FILL_SCOPE( scope_var )         \\\n    if ( j.contains( #scope_var ) )          \\\n    {                                        \\\n        j[#scope_var].get_to( p.scope_var ); \\\n    }\n\n    SPTF_FILL_SCOPE( playlist_modify_public )\n    SPTF_FILL_SCOPE( playlist_read_private )\n    SPTF_FILL_SCOPE( playlist_modify_private )\n    SPTF_FILL_SCOPE( playlist_read_collaborative )\n    SPTF_FILL_SCOPE( user_read_playback_position )\n    SPTF_FILL_SCOPE( user_read_recently_played )\n    SPTF_FILL_SCOPE( user_top_read )\n    SPTF_FILL_SCOPE( user_follow_modify )\n    SPTF_FILL_SCOPE( user_follow_read )\n    SPTF_FILL_SCOPE( user_library_read )\n    SPTF_FILL_SCOPE( user_library_modify )\n    SPTF_FILL_SCOPE( user_read_private )\n    SPTF_FILL_SCOPE( user_read_email )\n\n#undef SPTF_FILL_SCOPE\n}\n\n} // namespace sptf\n"
  },
  {
    "path": "foo_spotify/backend/webapi_auth_scopes.h",
    "content": "#pragma once\n\n#include <nonstd/span.hpp>\n\n#include <string_view>\n\nnamespace sptf\n{\n\nstruct WebApiAuthScopes\n{\n    WebApiAuthScopes() = default;\n    WebApiAuthScopes( nonstd::span<const std::wstring_view> scopes );\n    std::wstring ToWebString() const;\n\n    bool playlist_modify_public = false;\n    bool playlist_read_private = false;\n    bool playlist_modify_private = false;\n    bool playlist_read_collaborative = false;\n    bool user_read_playback_position = false;\n    bool user_read_recently_played = false;\n    bool user_top_read = false;\n    bool user_follow_modify = false;\n    bool user_follow_read = false;\n    bool user_library_read = false;\n    bool user_library_modify = false;\n    bool user_read_private = false;\n    bool user_read_email = false;\n};\n\nvoid to_json( nlohmann::json& j, const WebApiAuthScopes& p );\nvoid from_json( const nlohmann::json& j, WebApiAuthScopes& p );\n\n} // namespace sptf\n"
  },
  {
    "path": "foo_spotify/backend/webapi_backend.cpp",
    "content": "#include <stdafx.h>\n\n#include \"webapi_backend.h\"\n\n#include <backend/webapi_auth.h>\n#include <backend/webapi_objects/webapi_media_objects.h>\n#include <backend/webapi_objects/webapi_paging_object.h>\n#include <backend/webapi_objects/webapi_user.h>\n#include <fb2k/advanced_config.h>\n#include <utils/abort_manager.h>\n#include <utils/json_std_extenders.h>\n#include <utils/sleeper.h>\n\n#include <component_urls.h>\n\n#include <qwr/fb2k_adv_config.h>\n#include <qwr/file_helpers.h>\n#include <qwr/final_action.h>\n#include <qwr/string_helpers.h>\n#include <qwr/type_traits.h>\n#include <qwr/winapi_error_helpers.h>\n\n#include <filesystem>\n#include <unordered_set>\n\n// TODO: replace unique_ptr with shared_ptr wherever needed to avoid copying\n\nnamespace fs = std::filesystem;\n\nnamespace\n{\n\nconstexpr size_t kRpsLimit = 2;\n\n}\n\nnamespace sptf\n{\n\nWebApi_Backend::WebApi_Backend( AbortManager& abortManager )\n    : abortManager_( abortManager )\n    , shouldLogWebApiRequest_( config::advanced::logging_webapi_request )\n    , shouldLogWebApiResponse_( config::advanced::logging_webapi_response )\n    , rpsLimiter_( kRpsLimit )\n    , client_( url::spotifyApi, GetClientConfig() )\n    , trackCache_( \"tracks\" )\n    , artistCache_( \"artists\" )\n    , albumImageCache_( \"albums\" )\n    , artistImageCache_( \"artists\" )\n    , pAuth_( std::make_unique<WebApiAuthorizer>( GetClientConfig(), abortManager ) )\n{\n}\n\nWebApi_Backend::~WebApi_Backend()\n{\n}\n\nvoid WebApi_Backend::Finalize()\n{\n    cts_.cancel();\n    pAuth_.reset();\n}\n\nWebApiAuthorizer& WebApi_Backend::GetAuthorizer()\n{\n    return *pAuth_;\n}\n\nstd::unique_ptr<const sptf::WebApi_User> WebApi_Backend::GetUser( abort_callback& abort )\n{\n    if ( auto userOpt = userCache_.GetObjectFromCache();\n         userOpt )\n    {\n        return std::unique_ptr<sptf::WebApi_User>( std::move( *userOpt ) );\n    }\n    else\n    {\n        web::uri_builder builder;\n        builder.append_path( L\"me\" );\n\n        const auto responseJson = GetJsonResponse( builder.to_uri(), abort );\n        auto ret = responseJson.get<std::unique_ptr<WebApi_User>>();\n\n        userCache_.CacheObject( *ret );\n        return std::unique_ptr<sptf::WebApi_User>( std::move( ret ) );\n    }\n}\n\nvoid WebApi_Backend::RefreshCacheForTracks( nonstd::span<const std::string> trackIds, abort_callback& abort )\n{\n    constexpr size_t kMaxItemsPerRequest = 50;\n\n    // remove duplicates\n    const auto uniqueIds = trackIds | ranges::to<std::unordered_set<std::string>>;\n\n    for ( const auto& trackIdsChunk:\n          uniqueIds\n              | ranges::views::remove_if( [&]( const auto& id ) { return trackCache_.IsCached( id ); } )\n              | ranges::views::chunk( kMaxItemsPerRequest ) )\n    {\n        const auto trackIdsStr = qwr::unicode::ToWide( qwr::string::Join( trackIdsChunk | ranges::to_vector, ',' ) );\n\n        web::uri_builder builder;\n        builder\n            .append_path( L\"tracks\" )\n            .append_query( L\"ids\", trackIdsStr );\n\n        const auto responseJson = GetJsonResponse( builder.to_uri(), abort );\n        const auto tracksIt = responseJson.find( \"tracks\" );\n        qwr::QwrException::ExpectTrue( responseJson.cend() != tracksIt,\n                                       L\"Malformed track data response response: missing `tracks`\" );\n\n        auto ret = tracksIt->get<std::vector<std::unique_ptr<const WebApi_Track>>>();\n        trackCache_.CacheObjects( ret );\n    }\n}\n\nstd::unique_ptr<const sptf::WebApi_Track>\nWebApi_Backend::GetTrack( const std::string& trackId, abort_callback& abort, bool useRelink )\n{\n    // don't want to cache relinked tracks\n\n    if ( auto trackOpt = trackCache_.GetObjectFromCache( trackId );\n         !useRelink && trackOpt )\n    {\n        return std::unique_ptr<sptf::WebApi_Track>( std::move( *trackOpt ) );\n    }\n    else\n    {\n        web::uri_builder builder;\n        builder\n            .append_path( L\"tracks\" )\n            .append_path( qwr::unicode::ToWide( trackId ) );\n        if ( useRelink )\n        {\n            if ( const auto countryOpt = GetUser( abort )->country;\n                 countryOpt )\n            {\n                builder.append_query( L\"market\", qwr::unicode::ToWide( *countryOpt ) );\n            }\n        }\n\n        const auto responseJson = GetJsonResponse( builder.to_uri(), abort );\n        auto ret = responseJson.get<std::unique_ptr<WebApi_Track>>();\n\n        if ( !useRelink )\n        {\n            trackCache_.CacheObject( *ret );\n        }\n        return std::unique_ptr<sptf::WebApi_Track>( std::move( ret ) );\n    }\n}\n\nstd::vector<std::unique_ptr<const WebApi_Track>>\nWebApi_Backend::GetTracks( nonstd::span<const std::string> trackIds, abort_callback& abort )\n{\n    RefreshCacheForTracks( trackIds, abort );\n\n    return trackIds | ranges::views::transform( [&]( const auto& id ) -> std::unique_ptr<const WebApi_Track> {\n               assert( trackCache_.IsCached( id ) );\n               return std::move( *trackCache_.GetObjectFromCache( id ) );\n           } )\n           | ranges::to_vector;\n}\n\nstd::tuple<\n    std::vector<std::unique_ptr<const WebApi_Track>>,\n    std::vector<std::unique_ptr<const WebApi_LocalTrack>>>\nWebApi_Backend::GetTracksFromPlaylist( const std::string& playlistId, abort_callback& abort )\n{\n    constexpr size_t kMaxItemsPerRequest = 100;\n\n    auto requestUri = [&] {\n        web::uri_builder builder;\n        builder\n            .append_path( fmt::format( L\"playlists/{}/tracks\", qwr::unicode::ToWide( playlistId ) ) )\n            .append_query( L\"limit\", kMaxItemsPerRequest, false );\n\n        return builder.to_uri();\n    }();\n\n    std::vector<std::unique_ptr<const WebApi_Track>> tracks;\n    std::vector<std::unique_ptr<const WebApi_LocalTrack>> localTracks;\n    while ( true )\n    {\n        const auto responseJson = GetJsonResponse( requestUri, abort );\n        const auto pPagingObject = responseJson.get<std::unique_ptr<const WebApi_PagingObject>>();\n\n        auto playlistTracks = pPagingObject->items.get<std::vector<std::unique_ptr<WebApi_PlaylistTrack>>>();\n        for ( auto& playlistTrack: playlistTracks )\n        {\n            std::visit( [&]( auto&& arg ) {\n                using T = std::decay_t<decltype( arg )>;\n                if constexpr ( std::is_same_v<T, WebApi_Track> )\n                {\n                    tracks.emplace_back( std::make_unique<T>( std::move( arg ) ) );\n                }\n                else if constexpr ( std::is_same_v<T, WebApi_LocalTrack> )\n                {\n                    localTracks.emplace_back( std::make_unique<T>( std::move( arg ) ) );\n                }\n                else\n                {\n                    static_assert( qwr::always_false_v<T>, \"non-exhaustive visitor!\" );\n                }\n            },\n                        *playlistTrack->track );\n        }\n\n        if ( !pPagingObject->next )\n        {\n            break;\n        }\n\n        requestUri = *pPagingObject->next;\n    }\n\n    trackCache_.CacheObjects( tracks );\n    return { std::move( tracks ), std::move( localTracks ) };\n}\n\nstd::vector<std::unique_ptr<const sptf::WebApi_Track>>\nWebApi_Backend::GetTracksFromAlbum( const std::string& albumId, abort_callback& abort )\n{\n    std::shared_ptr<WebApi_Album_Simplified> album;\n    web::uri requestUri;\n    std::vector<std::unique_ptr<WebApi_Track_Simplified>> ret;\n    while ( true )\n    {\n        const auto responseJson = [&] {\n            if ( requestUri.is_empty() )\n            { // first paging object (and uri) is retrieved from album\n                web::uri_builder builder;\n                builder.append_path( fmt::format( L\"albums/{}\", qwr::unicode::ToWide( albumId ) ) );\n\n                const auto responseJson = GetJsonResponse( builder.to_uri(), abort );\n                responseJson.get_to( album );\n\n                const auto tracksIt = responseJson.find( \"tracks\" );\n                qwr::QwrException::ExpectTrue( responseJson.cend() != tracksIt,\n                                               L\"Malformed track data response: missing `tracks`\" );\n\n                return *tracksIt;\n            }\n            else\n            {\n                return GetJsonResponse( requestUri, abort );\n            }\n        }();\n\n        const auto pPagingObject = responseJson.get<std::unique_ptr<const WebApi_PagingObject>>();\n\n        auto newData = pPagingObject->items.get<std::vector<std::unique_ptr<WebApi_Track_Simplified>>>();\n        ret.insert( ret.end(), make_move_iterator( newData.begin() ), make_move_iterator( newData.end() ) );\n\n        if ( !pPagingObject->next )\n        {\n            break;\n        }\n\n        requestUri = *pPagingObject->next;\n    }\n\n    auto newRet = ranges::views::transform( ret, [&]( auto&& elem ) {\n                      return std::make_unique<const WebApi_Track>( std::move( elem ), album );\n                  } )\n                  | ranges::to_vector;\n    trackCache_.CacheObjects( newRet );\n    return newRet;\n}\n\nstd::vector<std::unique_ptr<const WebApi_Track>>\nWebApi_Backend::GetTopTracksForArtist( const std::string& artistId, abort_callback& abort )\n{\n    const auto countryOpt = GetUser( abort )->country;\n    qwr::QwrException::ExpectTrue( countryOpt.has_value(),\n                                   \"Adding artist top tracks requires `user-read-private` permission.\\n\"\n                                   \"Re-login to update your permission scope.\" );\n\n    web::uri_builder builder;\n    builder\n        .append_path( L\"artists\" )\n        .append_path( qwr::unicode::ToWide( artistId ) )\n        .append_path( L\"top-tracks\" )\n        .append_query( L\"market\", qwr::unicode::ToWide( *countryOpt ) );\n\n    const auto responseJson = GetJsonResponse( builder.to_uri(), abort );\n\n    const auto tracksIt = responseJson.find( \"tracks\" );\n    qwr::QwrException::ExpectTrue( responseJson.cend() != tracksIt,\n                                   L\"Malformed track data response response: missing `tracks`\" );\n\n    auto ret = tracksIt->get<std::vector<std::unique_ptr<const WebApi_Track>>>();\n    trackCache_.CacheObjects( ret );\n    return ret;\n}\n\nstd::vector<std::unordered_multimap<std::string, std::string>>\nWebApi_Backend::GetMetaForTracks( nonstd::span<const std::unique_ptr<const WebApi_Track>> tracks )\n{\n    std::vector<std::unordered_multimap<std::string, std::string>> ret;\n    for ( const auto& track: tracks )\n    {\n        auto& curMap = ret.emplace_back();\n\n        // This length will be overriden during playback\n        curMap.emplace( \"SPTF_LENGTH\", fmt::format( \"{}\", track->duration_ms ) );\n\n        curMap.emplace( \"TITLE\", track->name );\n        curMap.emplace( \"TRACKNUMBER\", fmt::format( \"{}\", track->track_number ) );\n        curMap.emplace( \"DISCNUMBER\", fmt::format( \"{}\", track->disc_number ) );\n\n        for ( const auto& artist: track->artists )\n        {\n            curMap.emplace( \"ARTIST\", artist->name );\n        }\n\n        const auto& album = track->album;\n        curMap.emplace( \"ALBUM\", album->name );\n        curMap.emplace( \"DATE\", album->release_date );\n\n        for ( const auto& artist: album->artists )\n        {\n            curMap.emplace( \"ALBUM ARTIST\", artist->name );\n        }\n    }\n\n    // TODO: cache data (<https://fy.3dyd.com/help/titleformatting/#Metadata_length_limitations> might be useful)\n    // TODO: check webapi_objects for other fields\n\n    return ret;\n}\n\nvoid WebApi_Backend::RefreshCacheForArtists( nonstd::span<const std::string> artistIds, abort_callback& abort )\n{\n    // remove duplicates\n    const auto uniqueIds = artistIds | ranges::to<std::unordered_set<std::string>>;\n\n    for ( const auto& idsChunk:\n          uniqueIds\n              | ranges::views::remove_if( [&]( const auto& id ) { return artistCache_.IsCached( id ); } )\n              | ranges::views::chunk( 50 ) )\n    {\n        const auto idsStr = qwr::unicode::ToWide( qwr::string::Join( idsChunk | ranges::to_vector, ',' ) );\n\n        web::uri_builder builder;\n        builder\n            .append_path( L\"artists\" )\n            .append_query( L\"ids\", idsStr );\n\n        const auto responseJson = GetJsonResponse( builder.to_uri(), abort );\n        const auto artistsIt = responseJson.find( \"artists\" );\n        qwr::QwrException::ExpectTrue( responseJson.cend() != artistsIt,\n                                       L\"Malformed track data response response: missing `artists`\" );\n\n        auto ret = artistsIt->get<std::vector<std::unique_ptr<const WebApi_Artist>>>();\n        artistCache_.CacheObjects( ret );\n    }\n}\n\nstd::unique_ptr<const WebApi_Artist>\nWebApi_Backend::GetArtist( const std::string& artistId, abort_callback& abort )\n{\n    if ( auto objectOpt = artistCache_.GetObjectFromCache( artistId );\n         objectOpt )\n    {\n        return std::unique_ptr<const WebApi_Artist>( std::move( *objectOpt ) );\n    }\n    else\n    {\n        web::uri_builder builder;\n        builder\n            .append_path( L\"artists\" )\n            .append_path( qwr::unicode::ToWide( artistId ) );\n\n        const auto responseJson = GetJsonResponse( builder.to_uri(), abort );\n        auto ret = responseJson.get<std::unique_ptr<const WebApi_Artist>>();\n        artistCache_.CacheObject( *ret );\n        return std::unique_ptr<const WebApi_Artist>( std::move( ret ) );\n    }\n}\n\nfs::path WebApi_Backend::GetAlbumImage( const std::string& albumId, const std::string& imgUrl, abort_callback& abort )\n{\n    return albumImageCache_.GetImage( albumId, imgUrl, abort );\n}\n\nfs::path WebApi_Backend::GetArtistImage( const std::string& artistId, const std::string& imgUrl, abort_callback& abort )\n{\n    return artistImageCache_.GetImage( artistId, imgUrl, abort );\n}\n\nweb::http::client::http_client_config WebApi_Backend::GetClientConfig()\n{\n    const auto proxyUrl = qwr::unicode::ToWide( sptf::config::advanced::network_proxy.GetValue() );\n    const auto proxyUsername = qwr::unicode::ToWide( sptf::config::advanced::network_proxy_username.GetValue() );\n    const auto proxyPassword = qwr::unicode::ToWide( sptf::config::advanced::network_proxy_password.GetValue() );\n\n    web::http::client::http_client_config config;\n    if ( !proxyUrl.empty() )\n    {\n        web::web_proxy proxy( web::uri::encode_uri( proxyUrl ) );\n        if ( !proxyUsername.empty() && !proxyPassword.empty() )\n        {\n            proxy.set_credentials( web::credentials{ proxyUsername, proxyPassword } );\n        }\n\n        config.set_proxy( std::move( proxy ) );\n    }\n\n    return config;\n}\n\nnlohmann::json WebApi_Backend::GetJsonResponse( const web::uri& requestUri, abort_callback& abort )\n{\n    return ParseResponse( GetResponse( requestUri, abort ) );\n}\n\nweb::http::http_response WebApi_Backend::GetResponse( const web::uri& requestUri, abort_callback& abort )\n{\n    const auto adjustedRequestUri = [&] {\n        const auto uriStr = requestUri.to_string();\n        const auto baseUriStr = client_.base_uri().to_string();\n        if ( uriStr._Starts_with( baseUriStr ) )\n        {\n            return web::uri{ uriStr.data() + baseUriStr.size() };\n        }\n        else\n        {\n            return requestUri;\n        }\n    }();\n\n    if ( shouldLogWebApiRequest_ )\n    {\n        FB2K_console_formatter() << SPTF_UNDERSCORE_NAME \" (debug): request:\\n\"\n                                 << qwr::unicode::ToU8( adjustedRequestUri.to_string() );\n    }\n\n    web::http::http_request req( web::http::methods::GET );\n    req.headers().add( L\"Authorization\", fmt::format( L\"Bearer {}\", pAuth_->GetAccessToken( abort ) ) );\n    req.headers().add( L\"Accept\", L\"application/json\" );\n    req.headers().set_content_type( L\"application/json\" );\n\n    req.set_request_uri( adjustedRequestUri );\n\n    rpsLimiter_.WaitForRequestAvailability( abort );\n    qwr::QwrException::ExpectTrue( !abort.is_aborting(), \"Abort was signaled, canceling request...\" );\n\n    auto ctsToken = cts_.get_token();\n    auto localCts = Concurrency::cancellation_token_source::create_linked_source( ctsToken );\n    const auto abortableScope = abortManager_.GetAbortableScope( [&localCts] { localCts.cancel(); }, abort );\n\n    web::http::http_response response;\n    for ( size_t i = 0; i < 3; ++i )\n    {\n        response = client_.request( req, localCts.get_token() ).get();\n        if ( response.status_code() != 429 )\n        {\n            break;\n        }\n\n        const auto it = response.headers().find( L\"Retry-After\" );\n        qwr::QwrException::ExpectTrue( it != response.headers().end(), \"Request failed with 429 error, but does not contain a `Retry-After` header\" );\n\n        const auto& [_, retryHeader] = *it;\n        const auto retryInMsOpt = qwr::string::GetNumber<uint32_t>( qwr::unicode::ToU8( retryHeader ) );\n        qwr::QwrException::ExpectTrue( retryInMsOpt.has_value(), \"Request failed with 429 error, but does not contain a valid number in `Retry-After` header\" );\n\n        const auto retryIn = std::chrono::milliseconds( *retryInMsOpt ) + std::chrono::seconds( 1 );\n        FB2K_console_formatter() << SPTF_UNDERSCORE_NAME \" (error):\\n\"\n                                 << fmt::format( L\"Rate limit reached: retrying in {} ms\", retryIn.count() );\n        if ( !SleepFor( retryIn, abort ) )\n        {\n            break;\n        }\n    }\n\n    if ( response.status_code() == 429 )\n    {\n        FB2K_console_formatter() << SPTF_UNDERSCORE_NAME \" (error):\\n\"\n                                 << fmt::format( L\"Rate limit reached: retry failed\" );\n    }\n\n    return response;\n}\n\nnlohmann::json WebApi_Backend::ParseResponse( const web::http::http_response& response )\n{\n    if ( response.status_code() != 200 )\n    {\n        throw qwr::QwrException( L\"{}: {}\\n\"\n                                 L\"Additional data: {}\\n\",\n                                 (int)response.status_code(),\n                                 response.reason_phrase(),\n                                 [&]() -> std::wstring {\n                                     try\n                                     {\n                                         const auto responseJson = nlohmann::json::parse( response.extract_string().get() );\n                                         return qwr::unicode::ToWide( responseJson.dump( 2 ) );\n                                     }\n                                     catch ( ... )\n                                     {\n                                         return response.to_string();\n                                     }\n                                 }() );\n    }\n\n    const auto responseJson = nlohmann::json::parse( response.extract_string().get() );\n    if ( shouldLogWebApiResponse_ )\n    {\n        FB2K_console_formatter() << SPTF_UNDERSCORE_NAME \" (debug): response:\\n\"\n                                 << responseJson.dump( 2 );\n    }\n    qwr::QwrException::ExpectTrue( responseJson.is_object(),\n                                   L\"Malformed track data response response: json is not an object\" );\n\n    return responseJson;\n}\n\n} // namespace sptf\n"
  },
  {
    "path": "foo_spotify/backend/webapi_backend.h",
    "content": "#pragma once\n\n#include <backend/webapi_cache.h>\n#include <utils/rps_limiter.h>\n\n#include <cpprest/http_client.h>\n#include <nonstd/span.hpp>\n\n#include <filesystem>\n#include <tuple>\n#include <unordered_map>\n#include <vector>\n\nnamespace sptf\n{\n\nstruct WebApi_User;\nstruct WebApi_Track;\nstruct WebApi_LocalTrack;\nstruct WebApi_Artist;\nclass WebApiAuthorizer;\nclass AbortManager;\n\nclass WebApi_Backend\n{\npublic:\n    WebApi_Backend( AbortManager& abortManager );\n    ~WebApi_Backend();\n\n    void Finalize();\n\n    WebApiAuthorizer& GetAuthorizer();\n\n    std::unique_ptr<const sptf::WebApi_User> GetUser( abort_callback& abort );\n\n    void RefreshCacheForTracks( nonstd::span<const std::string> trackIds, abort_callback& abort );\n\n    std::unique_ptr<const WebApi_Track>\n    GetTrack( const std::string& trackId, abort_callback& abort, bool useRelink = false );\n\n    std::vector<std::unique_ptr<const WebApi_Track>>\n    GetTracks( nonstd::span<const std::string> trackIds, abort_callback& abort );\n\n    std::tuple<\n        std::vector<std::unique_ptr<const WebApi_Track>>,\n        std::vector<std::unique_ptr<const WebApi_LocalTrack>>>\n    GetTracksFromPlaylist( const std::string& playlistId, abort_callback& abort );\n\n    std::vector<std::unique_ptr<const WebApi_Track>>\n    GetTracksFromAlbum( const std::string& albumId, abort_callback& abort );\n\n    std::vector<std::unique_ptr<const WebApi_Track>>\n    GetTopTracksForArtist( const std::string& artistId, abort_callback& abort );\n\n    std::vector<std::unordered_multimap<std::string, std::string>>\n    GetMetaForTracks( nonstd::span<const std::unique_ptr<const WebApi_Track>> tracks );\n\n    void RefreshCacheForArtists( nonstd::span<const std::string> artistIds, abort_callback& abort );\n\n    std::unique_ptr<const WebApi_Artist>\n    GetArtist( const std::string& artistId, abort_callback& abort );\n\n    std::filesystem::path GetAlbumImage( const std::string& albumId, const std::string& imgUrl, abort_callback& abort );\n    std::filesystem::path GetArtistImage( const std::string& artistId, const std::string& imgUrl, abort_callback& abort );\n\nprivate:\n    static web::http::client::http_client_config GetClientConfig();\n\n    nlohmann::json GetJsonResponse( const web::uri& requestUri, abort_callback& abort );\n    web::http::http_response GetResponse( const web::uri& requestUri, abort_callback& abort );\n    nlohmann::json ParseResponse( const web::http::http_response& response );\n\nprivate:\n    AbortManager& abortManager_;\n    RpsLimiter rpsLimiter_;\n\n    bool shouldLogWebApiRequest_ = false;\n    bool shouldLogWebApiResponse_ = false;\n\n    pplx::cancellation_token_source cts_;\n    std::unique_ptr<WebApiAuthorizer> pAuth_;\n    web::http::client::http_client client_;\n\n    WebApi_UserCache userCache_;\n    WebApi_ObjectCache<WebApi_Track> trackCache_;\n    WebApi_ObjectCache<WebApi_Artist> artistCache_;\n\n    WebApi_ImageCache albumImageCache_;\n    WebApi_ImageCache artistImageCache_;\n};\n\n} // namespace sptf\n"
  },
  {
    "path": "foo_spotify/backend/webapi_cache.cpp",
    "content": "#include <stdafx.h>\n\n#include \"webapi_cache.h\"\n\n#include <backend/spotify_instance.h>\n#include <backend/webapi_objects/webapi_user.h>\n#include <utils/abort_manager.h>\n#include <utils/json_std_extenders.h>\n\n#include <qwr/winapi_error_helpers.h>\n\n// RODO: move to props\n#pragma comment( lib, \"Urlmon.lib\" )\n\nnamespace fs = std::filesystem;\n\nnamespace\n{\n\nusing namespace sptf;\n\nclass DownloadStatus : public IBindStatusCallback\n{\npublic:\n    DownloadStatus( abort_callback& abort );\n\npublic:\n    STDMETHOD( OnStartBinding )(\n        /* [in] */ DWORD dwReserved,\n        /* [in] */ IBinding __RPC_FAR* pib )\n    {\n        return E_NOTIMPL;\n    }\n\n    STDMETHOD( GetPriority )(\n        /* [out] */ LONG __RPC_FAR* pnPriority )\n    {\n        return E_NOTIMPL;\n    }\n\n    STDMETHOD( OnLowResource )(\n        /* [in] */ DWORD reserved )\n    {\n        return E_NOTIMPL;\n    }\n\n    STDMETHOD( OnProgress )(\n        /* [in] */ ULONG ulProgress,\n        /* [in] */ ULONG ulProgressMax,\n        /* [in] */ ULONG ulStatusCode,\n        /* [in] */ LPCWSTR wszStatusText );\n\n    STDMETHOD( OnStopBinding )(\n        /* [in] */ HRESULT hresult,\n        /* [unique][in] */ LPCWSTR szError )\n    {\n        return E_NOTIMPL;\n    }\n\n    STDMETHOD( GetBindInfo )(\n        /* [out] */ DWORD __RPC_FAR* grfBINDF,\n        /* [unique][out][in] */ BINDINFO __RPC_FAR* pbindinfo )\n    {\n        return E_NOTIMPL;\n    }\n\n    STDMETHOD( OnDataAvailable )(\n        /* [in] */ DWORD grfBSCF,\n        /* [in] */ DWORD dwSize,\n        /* [in] */ FORMATETC __RPC_FAR* pformatetc,\n        /* [in] */ STGMEDIUM __RPC_FAR* pstgmed )\n    {\n        return E_NOTIMPL;\n    }\n\n    STDMETHOD( OnObjectAvailable )(\n        /* [in] */ REFIID riid,\n        /* [iid_is][in] */ IUnknown __RPC_FAR* punk )\n    {\n        return E_NOTIMPL;\n    }\n\n    // IUnknown methods.  Note that IE never calls any of these methods, since\n    // the caller owns the IBindStatusCallback interface, so the methods all\n    // return zero/E_NOTIMPL.\n\n    STDMETHOD_( ULONG, AddRef )\n    ()\n    {\n        return 0;\n    }\n\n    STDMETHOD_( ULONG, Release )\n    ()\n    {\n        return 0;\n    }\n\n    STDMETHOD( QueryInterface )(\n        /* [in] */ REFIID riid,\n        /* [iid_is][out] */ void __RPC_FAR* __RPC_FAR* ppvObject )\n    {\n        return E_NOTIMPL;\n    }\n\nprivate:\n    std::unique_ptr<AbortManager::AbortableScope> pScope_;\n    std::mutex mutex_;\n    bool hasAborted_ = false;\n};\n\nDownloadStatus::DownloadStatus( abort_callback& abort )\n{\n    auto& am = SpotifyInstance::Get().GetAbortManager();\n    pScope_ = std::make_unique<AbortManager::AbortableScope>(\n        am.GetAbortableScope( [&] {\n            std::lock_guard lg( mutex_ );\n            hasAborted_ = true;\n        },\n                              abort ) );\n}\n\nHRESULT DownloadStatus::OnProgress( ULONG ulProgress, ULONG ulProgressMax,\n                                    ULONG ulStatusCode, LPCWSTR wszStatusText )\n{\n    std::lock_guard lg( mutex_ );\n    return ( hasAborted_ ? E_ABORT : S_OK );\n}\n\n} // namespace\n\nnamespace sptf\n{\n\nWebApi_UserCache::WebApi_UserCache()\n    : jsonCache_( \"\" )\n{\n}\n\nvoid WebApi_UserCache::CacheObject( const WebApi_User& object, bool force /*= false */ )\n{\n    std::lock_guard lock( cacheMutex_ );\n    jsonCache_.CacheObject_NonBlocking( object, \"me\", force );\n}\n\nstd::optional<std::unique_ptr<sptf::WebApi_User>> WebApi_UserCache::GetObjectFromCache()\n{\n    std::lock_guard lock( cacheMutex_ );\n    return jsonCache_.GetObjectFromCache_NonBlocking( \"me\" );\n}\n\nWebApi_ImageCache::WebApi_ImageCache( const std::string& cacheSubdir )\n    : cacheSubdir_( cacheSubdir )\n{\n}\n\nfs::path WebApi_ImageCache::GetImage( const std::string& id, const std::string& imgUrl, abort_callback& abort )\n{\n    std::lock_guard lock( cacheMutex_ );\n\n    const auto imagePath = path::WebApiCache() / \"images\" / cacheSubdir_ / fmt::format( \"{}.jpeg\", id );\n    if ( !fs::exists( imagePath ) )\n    {\n        fs::create_directories( imagePath.parent_path() );\n\n        const auto url_w = qwr::unicode::ToWide( imgUrl );\n\n        DownloadStatus ds( abort );\n        auto hr = URLDownloadToFile( nullptr, url_w.c_str(), imagePath.c_str(), 0, &ds );\n        if ( FAILED( hr ) )\n        {\n            fs::remove( imagePath ); // in case download was aborted midway\n            qwr::error::CheckHR( hr, \"URLDownloadToFile\" );\n        }\n    }\n    assert( fs::exists( imagePath ) );\n    return imagePath;\n}\n\n} // namespace sptf\n"
  },
  {
    "path": "foo_spotify/backend/webapi_cache.h",
    "content": "#pragma once\n\n#include <nonstd/span.hpp>\n#include <qwr/file_helpers.h>\n\n#include <filesystem>\n#include <memory>\n#include <mutex>\n\nnamespace sptf\n{\n\ntemplate <typename T>\nclass WebApi_JsonCache\n{\npublic:\n    WebApi_JsonCache( const std::string& cacheSubdir )\n        : cacheSubdir_( cacheSubdir )\n    {\n    }\n\n    std::optional<std::unique_ptr<T>>\n    GetObjectFromCache_NonBlocking( const std::string& filename )\n    {\n        namespace fs = std::filesystem;\n\n        const auto filePath = GetCachedPath( filename );\n        if ( !fs::exists( filePath ) )\n        {\n            return std::nullopt;\n        }\n\n        const auto data = qwr::file::ReadFile( filePath, CP_UTF8, false );\n        try\n        {\n            return nlohmann::json::parse( data ).get<std::unique_ptr<T>>();\n        }\n        catch ( const nlohmann::detail::exception& )\n        {\n            return std::nullopt;\n        }\n    }\n\n    void CacheObject_NonBlocking( const T& object, const std::string& filename, bool force )\n    {\n        namespace fs = std::filesystem;\n\n        const auto filePath = GetCachedPath( filename );\n        if ( fs::exists( filePath ) )\n        {\n            if ( !force )\n            {\n                return;\n            }\n            fs::remove( filePath );\n        }\n\n        fs::create_directories( filePath.parent_path() );\n        qwr::file::WriteFile( filePath, nlohmann::json( object ).dump( 2 ) );\n    }\n\n    bool IsCached_NonBlocking( const std::string& filename )\n    {\n        namespace fs = std::filesystem;\n\n        const auto filePath = GetCachedPath( filename );\n        return fs::exists( filePath );\n    }\n\nprivate:\n    std::filesystem::path GetCachedPath( const std::string& filename ) const\n    {\n        return path::WebApiCache() / \"data\" / cacheSubdir_ / fmt::format( \"{}.json\", filename );\n    }\n\nprivate:\n    std::string cacheSubdir_;\n};\n\ntemplate <typename T>\nclass WebApi_ObjectCache\n{\npublic:\n    WebApi_ObjectCache( const std::string& cacheSubdir )\n        : jsonCache_( cacheSubdir )\n    {\n    }\n\n    void CacheObject( const T& object, bool force = false )\n    {\n        std::lock_guard lock( cacheMutex_ );\n        jsonCache_.CacheObject_NonBlocking( object, object.id, force );\n    }\n\n    void CacheObjects( const nonstd::span<std::unique_ptr<T>> objects, bool force = false )\n    {\n        std::lock_guard lock( cacheMutex_ );\n        for ( const auto& pObject: objects )\n        {\n            jsonCache_.CacheObject_NonBlocking( *pObject, pObject->id, force );\n        }\n    }\n\n    void CacheObjects( const nonstd::span<std::unique_ptr<const T>> objects, bool force = false )\n    {\n        std::lock_guard lock( cacheMutex_ );\n        for ( const auto& pObject: objects )\n        {\n            jsonCache_.CacheObject_NonBlocking( *pObject, pObject->id, force );\n        }\n    }\n\n    std::optional<std::unique_ptr<T>>\n    GetObjectFromCache( const std::string& id )\n    {\n        std::lock_guard lock( cacheMutex_ );\n        return jsonCache_.GetObjectFromCache_NonBlocking( id );\n    }\n\n    bool IsCached( const std::string& id )\n    {\n        std::lock_guard lock( cacheMutex_ );\n        return jsonCache_.IsCached_NonBlocking( id );\n    }\n\nprivate:\n    std::mutex cacheMutex_;\n    WebApi_JsonCache<T> jsonCache_;\n};\n\nstruct WebApi_User;\n\nclass WebApi_UserCache\n{\npublic:\n    WebApi_UserCache();\n\n    void CacheObject( const WebApi_User& object, bool force = false );\n\n    std::optional<std::unique_ptr<WebApi_User>>\n    GetObjectFromCache();\n\nprivate:\n    std::mutex cacheMutex_;\n    WebApi_JsonCache<WebApi_User> jsonCache_;\n};\n\nclass WebApi_ImageCache\n{\npublic:\n    WebApi_ImageCache( const std::string& cacheSubdir );\n\n    std::filesystem::path GetImage( const std::string& id,\n                                    const std::string& imgUrl,\n                                    abort_callback& abort );\n\nprivate:\n    std::string cacheSubdir_;\n    std::mutex cacheMutex_;\n};\n\n} // namespace sptf\n"
  },
  {
    "path": "foo_spotify/backend/webapi_objects/webapi_album.cpp",
    "content": "#include <stdafx.h>\n\n#include \"webapi_album.h\"\n\n#include <backend/webapi_objects/webapi_media_objects.h>\n#include <utils/json_std_extenders.h>\n\nnamespace sptf\n{\n\nSPTF_NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE( WebApi_Album_Simplified, artists, images, release_date, name, id );\n\n} // namespace sptf\n"
  },
  {
    "path": "foo_spotify/backend/webapi_objects/webapi_album.h",
    "content": "#pragma once\n\n#include <memory>\n#include <string>\n#include <vector>\n\nnamespace sptf\n{\n\nstruct WebApi_Artist_Simplified;\nstruct WebApi_Image;\n\nstruct WebApi_Album_Simplified\n{\n    // album_group \tstring, optional \tThe field is present when getting an artists albums. Possible values are album, single, compilation, appears_on. Compare to album_type this field represents relationship between the artist and the album.\n    // album_type \tstring \tThe type of the album: one of album, single, or compilation.\n    // available_markets \tarray of strings \tThe markets in which the album is available: ISO 3166-1 alpha-2 country codes. Note that an album is considered available in a market when at least 1 of its tracks is available in that market.\n    // external_urls \tan external URL object \tKnown external URLs for this album.\n    // release_date_precision \tstring \tThe precision with which release_date value is known: year , month , or day.\n    // restrictions \ta restrictions object \tPart of the response when Track Relinking is applied, the original track is not available in the given market, and Spotify did not have any tracks to relink it with. The track response will still contain metadata for the original track, and a restrictions object containing the reason why the track is not available: \"restrictions\" : {\"reason\" : \"market\"}\n\n    std::vector<std::unique_ptr<WebApi_Artist_Simplified>> artists;\n    std::vector<std::unique_ptr<WebApi_Image>> images;\n    std::string id;\n    std::string release_date;\n    std::string name;\n};\n\nvoid to_json( nlohmann::json& j, const WebApi_Album_Simplified& p );\nvoid from_json( const nlohmann::json& j, WebApi_Album_Simplified& p );\n\n} // namespace sptf"
  },
  {
    "path": "foo_spotify/backend/webapi_objects/webapi_artist.cpp",
    "content": "#include <stdafx.h>\n\n#include \"webapi_artist.h\"\n\n#include <backend/webapi_objects/webapi_media_objects.h>\n#include <utils/json_std_extenders.h>\n\nnamespace sptf\n{\n\nSPTF_NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE( WebApi_Artist_Simplified, id, name );\nSPTF_NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE( WebApi_Artist, id, images, name, popularity );\n\n} // namespace sptf\n"
  },
  {
    "path": "foo_spotify/backend/webapi_objects/webapi_artist.h",
    "content": "#pragma once\n\n#include <string>\n\nnamespace sptf\n{\n\nstruct WebApi_Image;\n\nstruct WebApi_Artist_Simplified\n{\n    // external_urls \tan external URL object \tKnown external URLs for this artist.\n\n    std::string id;\n    std::string name;\n};\n\nstruct WebApi_Artist\n{\n    // external_urls \tan external URL object \tKnown external URLs for this artist.\n    // followers \tA followers object \tInformation about the followers of the artist.\n    // genres \tarray of strings \tA list of the genres the artist is associated with. For example: \"Prog Rock\" , \"Post-Grunge\". (If not yet classified, the array is empty.)\n\n    std::string id;\n    std::vector<std::unique_ptr<WebApi_Image>> images;\n    std::string name;\n    uint32_t popularity;\n};\n\nvoid to_json( nlohmann::json& j, const WebApi_Artist_Simplified& p );\nvoid from_json( const nlohmann::json& j, WebApi_Artist_Simplified& p );\n\nvoid to_json( nlohmann::json& j, const WebApi_Artist& p );\nvoid from_json( const nlohmann::json& j, WebApi_Artist& p );\n\n} // namespace sptf"
  },
  {
    "path": "foo_spotify/backend/webapi_objects/webapi_image.cpp",
    "content": "#include <stdafx.h>\n\n#include \"webapi_image.h\"\n\nnamespace sptf\n{\n\nSPTF_NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE( WebApi_Image, height, url, width );\n\n} // namespace sptf\n"
  },
  {
    "path": "foo_spotify/backend/webapi_objects/webapi_image.h",
    "content": "#pragma once\n\n#include <memory>\n#include <string>\n\nnamespace sptf\n{\n\nstruct WebApi_Image\n{\n    uint32_t height;\n    std::string url;\n    uint32_t width;\n};\n\nvoid to_json( nlohmann::json& j, const WebApi_Image& p );\nvoid from_json( const nlohmann::json& j, WebApi_Image& p );\n\n} // namespace sptf"
  },
  {
    "path": "foo_spotify/backend/webapi_objects/webapi_media_objects.h",
    "content": "#pragma once\n\n#include <backend/webapi_objects/webapi_album.h>\n#include <backend/webapi_objects/webapi_artist.h>\n#include <backend/webapi_objects/webapi_image.h>\n#include <backend/webapi_objects/webapi_playlist_track.h>\n#include <backend/webapi_objects/webapi_restriction.h>\n#include <backend/webapi_objects/webapi_track.h>\n#include <backend/webapi_objects/webapi_track_link.h>\n"
  },
  {
    "path": "foo_spotify/backend/webapi_objects/webapi_paging_object.cpp",
    "content": "#include <stdafx.h>\n\n#include \"webapi_paging_object.h\"\n\n#include <utils/json_std_extenders.h>\n\nnamespace sptf\n{\n\nvoid from_json( const nlohmann::json& nlohmann_json_j, WebApi_PagingObject& nlohmann_json_t )\n{\n    NLOHMANN_JSON_EXPAND( NLOHMANN_JSON_PASTE( NLOHMANN_JSON_FROM, items, limit, next, offset, previous, total ) )\n}\n\n} // namespace sptf\n"
  },
  {
    "path": "foo_spotify/backend/webapi_objects/webapi_paging_object.h",
    "content": "#pragma once\n\n#include <memory>\n#include <optional>\n#include <string>\n\nnamespace sptf\n{\n\nstruct WebApi_PagingObject\n{\n    // href \tstring \tA link to the Web API endpoint returning the full result of the request.\n    nlohmann::json items;\n    size_t limit;\n    std::optional<std::wstring> next;\n    size_t offset;\n    std::optional<std::wstring> previous;\n    size_t total;\n};\n\nvoid from_json( const nlohmann::json& j, WebApi_PagingObject& p );\n\n} // namespace sptf\n"
  },
  {
    "path": "foo_spotify/backend/webapi_objects/webapi_playlist_track.cpp",
    "content": "#include <stdafx.h>\n\n#include \"webapi_playlist_track.h\"\n\n#include <backend/webapi_objects/webapi_media_objects.h>\n#include <utils/json_std_extenders.h>\n\nnamespace sptf\n{\n\nvoid to_json( nlohmann::json& j, const WebApi_PlaylistTrack& p )\n{\n    std::visit( [&j]( auto&& arg ) {\n        j[\"track\"] = arg;\n    },\n                *p.track );\n}\n\nvoid from_json( const nlohmann::json& j, WebApi_PlaylistTrack& p )\n{\n    if ( j.at( \"is_local\" ).get<bool>() )\n    {\n        p.track = std::make_unique<std::variant<WebApi_Track, WebApi_LocalTrack>>( j.at( \"track\" ).get<WebApi_LocalTrack>() );\n    }\n    else\n    {\n        p.track = std::make_unique<std::variant<WebApi_Track, WebApi_LocalTrack>>( j.at( \"track\" ).get<WebApi_Track>() );\n    }\n}\n\nSPTF_NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE( WebApi_LocalTrack, uri, name );\n\n} // namespace sptf\n"
  },
  {
    "path": "foo_spotify/backend/webapi_objects/webapi_playlist_track.h",
    "content": "#pragma once\n\n#include <memory>\n#include <string>\n#include <variant>\n\nnamespace sptf\n{\n\nstruct WebApi_Track;\n\nstruct WebApi_LocalTrack\n{\n    std::string uri;\n    std::optional<std::string> name;\n};\n\nstruct WebApi_PlaylistTrack\n{\n    // added_at \ta timestamp \tThe date and time the track was added. Note that some very old playlists may return null in this field.\n    // added_by \ta user object \tThe Spotify user who added the track. Note that some very old playlists may return null in this field.\n    std::unique_ptr<std::variant<WebApi_Track, WebApi_LocalTrack>> track;\n};\n\nvoid to_json( nlohmann::json& j, const WebApi_PlaylistTrack& p );\nvoid from_json( const nlohmann::json& j, WebApi_PlaylistTrack& p );\n\nvoid to_json( nlohmann::json& j, const WebApi_LocalTrack& p );\nvoid from_json( const nlohmann::json& j, WebApi_LocalTrack& p );\n\n} // namespace sptf\n"
  },
  {
    "path": "foo_spotify/backend/webapi_objects/webapi_restriction.cpp",
    "content": "#include <stdafx.h>\n\n#include \"webapi_restriction.h\"\n\nnamespace sptf\n{\n\nSPTF_NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE( WebApi_Restriction, reason );\n\n} // namespace sptf\n"
  },
  {
    "path": "foo_spotify/backend/webapi_objects/webapi_restriction.h",
    "content": "#pragma once\n\n#include <memory>\n#include <string>\n\nnamespace sptf\n{\n\nstruct WebApi_Restriction\n{\n    std::string reason;\n};\n\nvoid to_json( nlohmann::json& j, const WebApi_Restriction& p );\nvoid from_json( const nlohmann::json& j, WebApi_Restriction& p );\n\n} // namespace sptf"
  },
  {
    "path": "foo_spotify/backend/webapi_objects/webapi_track.cpp",
    "content": "#include <stdafx.h>\n\n#include \"webapi_track.h\"\n\n#include <backend/webapi_objects/webapi_media_objects.h>\n#include <utils/json_std_extenders.h>\n\nnamespace sptf\n{\n\nWebApi_Track::WebApi_Track( std::unique_ptr<WebApi_Track_Simplified> trackSimplified,\n                            std::shared_ptr<const WebApi_Album_Simplified> albumSimplified )\n{\n    album = albumSimplified;\n    artists = std::move( trackSimplified->artists );\n    disc_number = trackSimplified->disc_number;\n    duration_ms = trackSimplified->duration_ms;\n    name = trackSimplified->name;\n    linked_from = std::move( trackSimplified->linked_from );\n    restrictions = std::move( trackSimplified->restrictions );\n    preview_url = trackSimplified->preview_url;\n    track_number = trackSimplified->track_number;\n    id = trackSimplified->id;\n}\n\nvoid to_json( nlohmann::json& nlohmann_json_j, const WebApi_Track_Simplified& nlohmann_json_t )\n{\n    // we don't need to save `restrictions`, since it's only used on initial parsing\n    NLOHMANN_JSON_EXPAND( NLOHMANN_JSON_PASTE( NLOHMANN_JSON_TO, artists, disc_number, duration_ms, linked_from, name, preview_url, track_number, id ) )\n}\n\nvoid from_json( const nlohmann::json& nlohmann_json_j, WebApi_Track_Simplified& nlohmann_json_t )\n{\n    NLOHMANN_JSON_EXPAND( NLOHMANN_JSON_PASTE( NLOHMANN_JSON_FROM, artists, disc_number, duration_ms, name, preview_url, track_number, id ) )\n    if ( nlohmann_json_j.contains( \"linked_from\" ) )\n    {\n        NLOHMANN_JSON_FROM( linked_from )\n    }\n    if ( nlohmann_json_j.contains( \"restrictions\" ) )\n    {\n        NLOHMANN_JSON_FROM( restrictions )\n    }\n}\n\nvoid to_json( nlohmann::json& nlohmann_json_j, const WebApi_Track& nlohmann_json_t )\n{\n    // we don't need to save `restrictions`, since it's only used on initial parsing\n    NLOHMANN_JSON_EXPAND( NLOHMANN_JSON_PASTE( NLOHMANN_JSON_TO, album, artists, disc_number, duration_ms, linked_from, name, preview_url, track_number, id ) )\n}\n\nvoid from_json( const nlohmann::json& nlohmann_json_j, WebApi_Track& nlohmann_json_t )\n{\n    NLOHMANN_JSON_EXPAND( NLOHMANN_JSON_PASTE( NLOHMANN_JSON_FROM, album, artists, disc_number, duration_ms, name, preview_url, track_number, id ) )\n    if ( nlohmann_json_j.contains( \"linked_from\" ) )\n    {\n        NLOHMANN_JSON_FROM( linked_from )\n    }\n    if ( nlohmann_json_j.contains( \"restrictions\" ) )\n    {\n        NLOHMANN_JSON_FROM( restrictions )\n    }\n}\n\n} // namespace sptf\n"
  },
  {
    "path": "foo_spotify/backend/webapi_objects/webapi_track.h",
    "content": "#pragma once\n\n#include <memory>\n#include <string>\n#include <vector>\n\nnamespace sptf\n{\n\nstruct WebApi_Album_Simplified;\nstruct WebApi_Artist_Simplified;\nstruct WebApi_Restriction;\nstruct WebApi_TrackLink;\n\nstruct WebApi_Track_Simplified\n{\n    // available_markets \tarray of strings \tA list of the countries in which the track can be played, identified by their ISO 3166-1 alpha-2 code.\n    // explicit \tBoolean \tWhether or not the track has explicit lyrics ( true = yes it does; false = no it does not OR unknown).\n    // external_urls \tan external URL object \tExternal URLs for this track.\n    // is_playable boolean Part of the response when Track Relinking is applied.If true, the track is playable in the given market.Otherwise false.\n    // is_local \tboolean \tWhether or not the track is from a local file.\n\n    std::vector<std::unique_ptr<WebApi_Artist_Simplified>> artists;\n    uint32_t disc_number;\n    uint32_t duration_ms;\n    std::string id;\n    std::optional<std::unique_ptr<WebApi_TrackLink>> linked_from;\n    std::optional<std::unique_ptr<WebApi_Restriction>> restrictions;\n    std::string name;\n    std::optional<std::string> preview_url;\n    uint32_t track_number;\n};\n\nstruct WebApi_Track\n{\n    WebApi_Track() = default;\n    WebApi_Track( std::unique_ptr<WebApi_Track_Simplified> trackSimplified, std::shared_ptr<const WebApi_Album_Simplified> albumSimplified );\n\n    //available_markets \tarray of strings \tA list of the countries in which the track can be played, identified by their ISO 3166-1 alpha-2 code.\n    //explicit \tBoolean \tWhether or not the track has explicit lyrics ( true = yes it does; false = no it does not OR unknown).\n    //external_ids \tan external ID object \tKnown external IDs for the track.\n    //external_urls \tan external URL object \tKnown external URLs for this track.\n    //is_playable boolean Part of the response when Track Relinking is applied.If true, the track is playable in the given market.Otherwise false.\n    //popularity \tinteger \tThe popularity of the track. The value will be between 0 and 100, with 100 being the most popular.\n    //The popularity of a track is a value between 0 and 100, with 100 being the most popular. The popularity is calculated by algorithm and is based, in the most part, on the total number of plays the track has had and how recent those plays are.\n    //Generally speaking, songs that are being played a lot now will have a higher popularity than songs that were played a lot in the past. Duplicate tracks (e.g. the same track from a single and an album) are rated independently. Artist and album popularity is derived mathematically from track popularity. Note that the popularity value may lag actual popularity by a few days: the value is not updated in real time.\n    //is_local \tboolean \tWhether or not the track is from a local file.\n\n    std::shared_ptr<const WebApi_Album_Simplified> album;\n    std::vector<std::unique_ptr<WebApi_Artist_Simplified>> artists;\n    uint32_t disc_number;\n    uint32_t duration_ms;\n    std::string id;\n    std::optional<std::unique_ptr<WebApi_TrackLink>> linked_from;\n    std::optional<std::unique_ptr<WebApi_Restriction>> restrictions;\n    std::string name;\n    std::optional<std::string> preview_url;\n    uint32_t track_number;\n};\n\nvoid to_json( nlohmann::json& j, const WebApi_Track_Simplified& p );\nvoid from_json( const nlohmann::json& j, WebApi_Track_Simplified& p );\n\nvoid to_json( nlohmann::json& j, const WebApi_Track& p );\nvoid from_json( const nlohmann::json& j, WebApi_Track& p );\n\n} // namespace sptf\n"
  },
  {
    "path": "foo_spotify/backend/webapi_objects/webapi_track_link.cpp",
    "content": "#include <stdafx.h>\n\n#include \"webapi_track_link.h\"\n\n#include <backend/webapi_objects/webapi_media_objects.h>\n#include <utils/json_std_extenders.h>\n\nnamespace sptf\n{\n\nSPTF_NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE( WebApi_TrackLink, id );\n\n} // namespace sptf\n"
  },
  {
    "path": "foo_spotify/backend/webapi_objects/webapi_track_link.h",
    "content": "#pragma once\n\n#include <memory>\n#include <string>\nnamespace sptf\n{\n\nstruct WebApi_TrackLink\n{\n    // external_urls \tan external URL object \tKnown external URLs for this track.\n    // href \tstring \tA link to the Web API endpoint providing full details of the track.\n    std::string id;\n    // type \tstring \tThe object type: track.\n    // uri \tstring \tThe Spotify URI for the track.\n};\n\nvoid to_json( nlohmann::json& j, const WebApi_TrackLink& p );\nvoid from_json( const nlohmann::json& j, WebApi_TrackLink& p );\n\n} // namespace sptf\n"
  },
  {
    "path": "foo_spotify/backend/webapi_objects/webapi_user.cpp",
    "content": "#include <stdafx.h>\n\n#include \"webapi_user.h\"\n\n#include <utils/json_std_extenders.h>\n\nnamespace sptf\n{\n\nvoid to_json( nlohmann::json& nlohmann_json_j, const WebApi_User& nlohmann_json_t )\n{\n    NLOHMANN_JSON_EXPAND( NLOHMANN_JSON_PASTE( NLOHMANN_JSON_TO, country, display_name, uri ) )\n}\n\nvoid from_json( const nlohmann::json& nlohmann_json_j, WebApi_User& nlohmann_json_t )\n{\n    NLOHMANN_JSON_EXPAND( NLOHMANN_JSON_PASTE( NLOHMANN_JSON_FROM, display_name, uri ) )\n    if ( nlohmann_json_j.contains( \"country\" ) )\n    {\n        NLOHMANN_JSON_FROM( country )\n    }\n}\n\n} // namespace sptf\n"
  },
  {
    "path": "foo_spotify/backend/webapi_objects/webapi_user.h",
    "content": "#pragma once\n\n#include <optional>\n#include <string>\n\nnamespace sptf\n{\n\nstruct WebApi_User\n{\n    std::optional<std::string> country;\n    std::optional<std::string> display_name;\n    //std::optional<std::string> email;\n    //external_urls \tan external URL object \tKnown external URLs for this user.\n    //followers \tA followers object \tInformation about the followers of the user.\n    //href \tstring \tA link to the Web API endpoint for this user.\n    std::string id;\n    //images \tan array of image objects \tThe users profile image.\n    //product \tstring \tThe users Spotify subscription level: premium, free, etc. (The subscription level open can be considered the same as free.) This field is only available when the current user has granted access to the user-read-private scope.\n    std::string uri;\n};\n\nvoid to_json( nlohmann::json& j, const WebApi_User& p );\nvoid from_json( const nlohmann::json& j, WebApi_User& p );\n\n} // namespace sptf\n"
  },
  {
    "path": "foo_spotify/component_defines.h",
    "content": "#pragma once\n\n// Generated by scripts from setup.py\n#include <commit_hash.h>\n#include <version.h>\n\n#define SPTF_NAME            \"Spotify Integration\"\n#define SPTF_UNDERSCORE_NAME \"foo_spotify\"\n#define SPTF_DLL_NAME        SPTF_UNDERSCORE_NAME \".dll\"\n\n#define SPTF_STRINGIFY_HELPER( x ) #x\n#define SPTF_STRINGIFY( x )        SPTF_STRINGIFY_HELPER( x )\n\n#ifdef SPTF_VERSION_PRERELEASE_TEXT\n#    define SPTF_VERSION_PRERELEASE \"-\" SPTF_VERSION_PRERELEASE_TEXT\n#    define SPTF_VERSION_METADATA   \"+\" SPTF_STRINGIFY( SPTF_COMMIT_HASH )\n#else\n#    define SPTF_VERSION_PRERELEASE \"\"\n#    define SPTF_VERSION_METADATA   \"\"\n#endif\n\n#ifdef _DEBUG\n#    define SPTF_VERSION_DEBUG_SUFFIX \" (Debug)\"\n#else\n#    define SPTF_VERSION_DEBUG_SUFFIX \"\"\n#endif\n\n#define SPTF_VERSION                                                                  \\\n    SPTF_STRINGIFY( SPTF_VERSION_MAJOR )                                              \\\n    \".\" SPTF_STRINGIFY( SPTF_VERSION_MINOR ) \".\" SPTF_STRINGIFY( SPTF_VERSION_PATCH ) \\\n        SPTF_VERSION_PRERELEASE SPTF_VERSION_METADATA\n#define SPTF_NAME_WITH_VERSION SPTF_NAME \" v\" SPTF_VERSION SPTF_VERSION_DEBUG_SUFFIX\n\n#define SPTF_ABOUT \\\n    SPTF_NAME_WITH_VERSION \" by TheQwertiest\"\n"
  },
  {
    "path": "foo_spotify/component_guids.h",
    "content": "#pragma once\n\nnamespace sptf::guid\n{\n\nconstexpr GUID acfu_source = { 0xbfbd48bc, 0x9f3b, 0x42bd, { 0x8e, 0xfc, 0x9d, 0x5a, 0xf1, 0x2f, 0xf3, 0xa1 } };\nconstexpr GUID adv_branch = { 0x3e2d241a, 0x306b, 0x49bc, { 0x80, 0xb3, 0x6a, 0x77, 0xe9, 0x21, 0x32, 0xc7 } };\nconstexpr GUID adv_branch_logging = { 0xa69190a1, 0x3abd, 0x4a45, { 0x9c, 0x4a, 0x66, 0xbd, 0xb, 0x7f, 0xec, 0x11 } };\nconstexpr GUID adv_branch_network = { 0x53328c11, 0x156e, 0x4b5c, { 0x8f, 0x82, 0xe5, 0x3d, 0x5d, 0xb5, 0x7c, 0x2b } };\nconstexpr GUID adv_var_network_proxy = { 0x2626706b, 0x19a9, 0x4ccf, { 0x85, 0xdd, 0x55, 0xd4, 0x2f, 0x8b, 0x57, 0x46 } };\nconstexpr GUID adv_var_network_proxy_username = { 0xd9e86980, 0xcee4, 0x4075, { 0x96, 0xef, 0x79, 0xed, 0xba, 0x87, 0x79, 0x58 } };\nconstexpr GUID adv_var_network_proxy_password = { 0xd138fb5, 0x3e6f, 0x48d6, { 0x9b, 0x44, 0x44, 0x6c, 0x78, 0xd4, 0x6f, 0xa3 } };\nconstexpr GUID adv_var_logging_webapi_debug = { 0xea784339, 0x21d7, 0x47ab, { 0xbc, 0xeb, 0x7a, 0xf7, 0xc, 0x8f, 0xb0, 0x18 } };\nconstexpr GUID adv_var_logging_webapi_request = { 0x90066d1d, 0x1233, 0x4fcc, { 0xab, 0xc3, 0xbc, 0x17, 0xb4, 0x68, 0x65, 0x84 } };\nconstexpr GUID adv_var_logging_webapi_response = { 0x349d3d49, 0xfffc, 0x4b32, { 0x8b, 0xf7, 0xc0, 0x78, 0x3a, 0x87, 0x5e, 0xa4 } };\nconstexpr GUID config_enable_normalization = { 0x7917bfbc, 0x3731, 0x4523, { 0xa4, 0x9e, 0xf8, 0xb3, 0x8e, 0xad, 0xbd, 0xb1 } };\nconstexpr GUID config_enable_private_mode = { 0xfd7aad3c, 0x3e8f, 0x45c2, { 0xaa, 0x62, 0xbe, 0xcc, 0x55, 0xe1, 0x2d, 0xfb } };\nconstexpr GUID config_libspotify_cache_size_in_mb = { 0xf23f3e, 0x5d86, 0x4092, { 0x8d, 0xf, 0xf1, 0x7d, 0x5b, 0xa1, 0x22, 0xf7 } };\nconstexpr GUID config_libspotify_cache_size_in_percent = { 0xf2107600, 0x4e31, 0x4039, { 0x9a, 0x5, 0xd3, 0x8f, 0x23, 0x25, 0x88, 0x72 } };\nconstexpr GUID config_preferred_bitrate = { 0xfaf55f2c, 0xe6d6, 0x4adc, { 0xae, 0x85, 0x3e, 0xcc, 0x8c, 0x19, 0xa, 0xe0 } };\nconstexpr GUID config_webapi_auth_scopes = { 0xabc0e6b2, 0x2569, 0x42ee, { 0xb8, 0xb0, 0x86, 0x7e, 0x3a, 0xc3, 0x21, 0x9 } };\nconstexpr GUID input = { 0xb376ad64, 0xe029, 0x40f6, { 0x89, 0xf8, 0xae, 0xc, 0xfa, 0x73, 0xa5, 0xa3 } };\nconstexpr GUID preferences = { 0x7285bbbd, 0x2109, 0x437c, { 0x8f, 0x3e, 0xaa, 0xa9, 0xc9, 0x90, 0x65, 0x2c } };\n\n} // namespace sptf::guid\n"
  },
  {
    "path": "foo_spotify/component_paths.cpp",
    "content": "#include <stdafx.h>\n\n#include \"component_paths.h\"\n\n#include <qwr/fbk2_paths.h>\n\nnamespace fs = std::filesystem;\n\nnamespace sptf::path\n{\n\nfs::path LibSpotifyCache()\n{\n    return qwr::path::Profile() / SPTF_UNDERSCORE_NAME / \"ls\" / \"cache\";\n}\nfs::path LibSpotifySettings()\n{\n    return qwr::path::Profile() / SPTF_UNDERSCORE_NAME / \"ls\" / \"settings\";\n}\n\nfs::path WebApiCache()\n{\n    return qwr::path::Profile() / SPTF_UNDERSCORE_NAME / \"wa\" / \"cache\";\n}\nfs::path WebApiSettings()\n{\n    return qwr::path::Profile() / SPTF_UNDERSCORE_NAME / \"wa\" / \"settings\";\n}\n\n} // namespace sptf::path"
  },
  {
    "path": "foo_spotify/component_paths.h",
    "content": "#pragma once\n\n#include <filesystem>\n\nnamespace sptf::path\n{\n\nstd::filesystem::path LibSpotifyCache();\nstd::filesystem::path LibSpotifySettings();\n\nstd::filesystem::path WebApiCache();\nstd::filesystem::path WebApiSettings();\n\n} // namespace sptf::guid\n"
  },
  {
    "path": "foo_spotify/component_urls.h",
    "content": "#pragma once\n\nnamespace sptf::url\n{\n\nconstexpr wchar_t accountsAuthenticate[] = L\"https://accounts.spotify.com/authorize\";\nconstexpr wchar_t accountsApi[] = L\"https://accounts.spotify.com/api/token\";\nconstexpr wchar_t spotifyApi[] = L\"https://api.spotify.com/v1\";\n\nconstexpr wchar_t redirectUri[] = L\"http://localhost:23018\";\n\nconstexpr wchar_t homepage[] = L\"https://github.com/TheQwertiest/\" SPTF_UNDERSCORE_NAME;\n\n} // namespace sptf::url\n"
  },
  {
    "path": "foo_spotify/dllmain.cpp",
    "content": "#include <stdafx.h>\n\n#include <backend/spotify_instance.h>\n#include <ui/ui_not_auth.h>\n\n#include <qwr/abort_callback.h>\n#include <qwr/delayed_executor.h>\n#include <qwr/error_popup.h>\n\nDECLARE_COMPONENT_VERSION( SPTF_NAME, SPTF_VERSION, SPTF_ABOUT );\n\nVALIDATE_COMPONENT_FILENAME( SPTF_DLL_NAME );\n\nusing namespace sptf;\n\nnamespace\n{\n\nbool HasComponent( const std::u8string& componentName )\n{\n    pfc::string8_fast temp;\n    for ( service_enum_t<componentversion> e; !e.finished(); ++e )\n    {\n        auto cv = e.get();\n        cv->get_file_name( temp );\n        if ( temp.c_str() == componentName )\n        {\n            return true;\n        }\n    }\n\n    return false;\n}\n\n} // namespace\n\nnamespace\n{\n\nclass sptf_initquit : public initquit\n{\npublic:\n    void on_init() override\n    {\n        qwr::DelayedExecutor::GetInstance().EnableExecution(); ///< Enable task processing (e.g. error popups)\n        if ( HasComponent( \"foo_input_spotify\" ) )\n        {\n            qwr::ReportErrorWithPopup( SPTF_UNDERSCORE_NAME,\n                                       \"!!!        `foo_input_spotify` component detected!             !!!\\n\"\n                                       \"!!! It is incompatible with `foo_spotify` and must be removed! !!!\\n\"\n                                       \"!!!           Otherwise foobar2000 *will* crash!               !!!\" );\n        }\n    }\n\n    void on_quit() override\n    { // Careful when changing invocation order here!\n        qwr::GlobalAbortCallback::GetInstance().Abort();\n        SpotifyInstance::Get().Finalize();\n        ui::NotAuthHandler::Get().CloseDialog();\n    }\n};\n\ninitquit_factory_t<sptf_initquit> g_initquit;\n\n} // namespace\n\nextern \"C\" BOOL WINAPI DllMain( HINSTANCE ins, DWORD reason, [[maybe_unused]] LPVOID lp )\n{\n    switch ( reason )\n    {\n    case DLL_PROCESS_ATTACH:\n    {\n        break;\n    }\n    case DLL_PROCESS_DETACH:\n    {\n        break;\n    }\n    default:\n        break;\n    }\n\n    return TRUE;\n}\n"
  },
  {
    "path": "foo_spotify/fb2k/acfu_integration.cpp",
    "content": "#include <stdafx.h>\n\n#include <component_urls.h>\n\n#include <qwr/acfu_integration.h>\n\nusing namespace sptf;\n\nnamespace\n{\n\nclass SptfSource\n    : public qwr::acfu::QwrSource\n{\npublic:\n    // ::acfu::source\n    GUID get_guid() override;\n    ::acfu::request::ptr create_request() override;\n\n    // qwr::acfu::github_conf\n    static pfc::string8 get_owner();\n    static pfc::string8 get_repo();\n\n    // qwr::acfu::QwrSource\n    std::string GetComponentName() const override;\n    std::string GetComponentFilename() const override;\n};\n\n} // namespace\n\nnamespace\n{\n\nGUID SptfSource::get_guid()\n{\n    return guid::acfu_source;\n}\n\n::acfu::request::ptr SptfSource::create_request()\n{\n    return fb2k::service_new<qwr::acfu::github_latest_release<SptfSource>>();\n}\n\npfc::string8 SptfSource::get_owner()\n{\n    return \"TheQwertiest\";\n}\n\npfc::string8 SptfSource::get_repo()\n{\n    return qwr::unicode::ToU8( std::wstring_view{ url::homepage } ).c_str();\n}\n\nstd::string SptfSource::GetComponentName() const\n{\n    return SPTF_NAME;\n}\n\nstd::string SptfSource::GetComponentFilename() const\n{\n    return SPTF_UNDERSCORE_NAME;\n}\n\nservice_factory_single_t<SptfSource> g_acfuSource;\n\n} // namespace\n"
  },
  {
    "path": "foo_spotify/fb2k/advanced_config.cpp",
    "content": "#include <stdafx.h>\n\n#include \"advanced_config.h\"\n\nnamespace\n{\n\nadvconfig_branch_factory branch_sptf(\n    \"Spotify Integration\", sptf::guid::adv_branch, advconfig_branch::guid_branch_tools, 0 );\nadvconfig_branch_factory branch_network(\n    \"Network: restart is required\", sptf::guid::adv_branch_network, sptf::guid::adv_branch, 0 );\nadvconfig_branch_factory branch_logging(\n    \"Logging: restart is required\", sptf::guid::adv_branch_logging, sptf::guid::adv_branch, 1 );\n\n} // namespace\n\nnamespace sptf::config::advanced\n{\n\nqwr::fb2k::AdvConfigString_MT network_proxy(\n    \"Proxy: url\",\n    sptf::guid::adv_var_network_proxy, sptf::guid::adv_branch_network, 0,\n    \"\" );\n\nqwr::fb2k::AdvConfigString_MT network_proxy_username(\n    \"Proxy: username\",\n    sptf::guid::adv_var_network_proxy_username, sptf::guid::adv_branch_network, 1,\n    \"\" );\n\nqwr::fb2k::AdvConfigString_MT network_proxy_password(\n    \"Proxy: password\",\n    sptf::guid::adv_var_network_proxy_password, sptf::guid::adv_branch_network, 2,\n    \"\" );\n\nqwr::fb2k::AdvConfigBool_MT logging_webapi_request(\n    \"Log Spotify Web API: request\",\n    sptf::guid::adv_var_logging_webapi_request, sptf::guid::adv_branch_logging, 0,\n    false );\n\nqwr::fb2k::AdvConfigBool_MT logging_webapi_response(\n    \"Log Spotify Web API: response\",\n    sptf::guid::adv_var_logging_webapi_response, sptf::guid::adv_branch_logging, 1,\n    false );\n\nqwr::fb2k::AdvConfigBool_MT logging_webapi_debug(\n    \"Log Spotify Web API: debug\",\n    sptf::guid::adv_var_logging_webapi_debug, sptf::guid::adv_branch_logging, 2,\n    false );\n\n} // namespace sptf::config::advanced\n"
  },
  {
    "path": "foo_spotify/fb2k/advanced_config.h",
    "content": "#pragma once\n\n#include <qwr/fb2k_adv_config.h>\n\nnamespace sptf::config::advanced\n{\n\nextern qwr::fb2k::AdvConfigString_MT network_proxy;\nextern qwr::fb2k::AdvConfigString_MT network_proxy_username;\nextern qwr::fb2k::AdvConfigString_MT network_proxy_password;\n\nextern qwr::fb2k::AdvConfigBool_MT logging_webapi_request;\nextern qwr::fb2k::AdvConfigBool_MT logging_webapi_response;\nextern qwr::fb2k::AdvConfigBool_MT logging_webapi_debug;\n\n} // namespace sptf::config::advanced\n"
  },
  {
    "path": "foo_spotify/fb2k/album_art.cpp",
    "content": "#include <stdafx.h>\n\n#include <backend/spotify_instance.h>\n#include <backend/spotify_object.h>\n#include <backend/webapi_backend.h>\n#include <backend/webapi_objects/webapi_media_objects.h>\n\nusing namespace sptf;\n\nnamespace\n{\n\nclass AlbumArtExtractorInstanceSpotify : public album_art_extractor_instance\n{\npublic:\n    AlbumArtExtractorInstanceSpotify( std::unique_ptr<const WebApi_Track> track, std::unique_ptr<const WebApi_Artist> artist );\n\n    album_art_data_ptr query( const GUID& p_what, abort_callback& p_abort ) override;\n\nprivate:\n    WebApi_Backend& waBackend_;\n    std::unique_ptr<const WebApi_Track> track_;\n    std::unique_ptr<const WebApi_Artist> artist_;\n};\n\nclass AlbumArtExtractorSpotify : public album_art_extractor\n{\npublic:\n    AlbumArtExtractorSpotify() = default;\n\n    bool is_our_path( const char* p_path, const char* p_extension ) override;\n    album_art_extractor_instance_ptr open( file_ptr p_filehint, const char* p_path, abort_callback& p_abort ) override;\n};\n\n} // namespace\n\nnamespace\n{\n\nAlbumArtExtractorInstanceSpotify::AlbumArtExtractorInstanceSpotify( std::unique_ptr<const WebApi_Track> track, std::unique_ptr<const WebApi_Artist> artist )\n    : waBackend_( SpotifyInstance::Get().GetWebApi_Backend() )\n    , track_( std::move( track ) )\n    , artist_( std::move( artist ) )\n{\n    assert( track_ );\n    assert( artist_ );\n}\n\nalbum_art_data_ptr AlbumArtExtractorInstanceSpotify::query( const GUID& p_what, abort_callback& p_abort )\n{\n    const auto imagePath = [&] {\n        if ( p_what == album_art_ids::cover_front )\n        {\n            if ( track_->album->images.empty() )\n            {\n                throw exception_album_art_not_found();\n            }\n\n            return waBackend_.GetAlbumImage( track_->album->id, track_->album->images[0]->url, p_abort );\n        }\n        else if ( p_what == album_art_ids::artist )\n        {\n            if ( artist_->images.empty() )\n            {\n                throw exception_album_art_not_found();\n            }\n\n            return waBackend_.GetArtistImage( artist_->id, artist_->images[0]->url, p_abort );\n        }\n        else\n        {\n            throw exception_album_art_not_found();\n        }\n    }();\n\n    pfc::string8_fast canPath;\n    filesystem::g_get_canonical_path( imagePath.u8string().c_str(), canPath );\n\n    file::ptr file;\n    filesystem::g_open( file, canPath, filesystem::open_mode_read, p_abort );\n\n    return album_art_data_impl::g_create( file.get_ptr(), (size_t)file->get_size_ex( p_abort ), p_abort );\n}\n\nbool AlbumArtExtractorSpotify::is_our_path( const char* p_path, const char* p_extension )\n{\n    return SpotifyFilteredTrack::IsValid( p_path, false );\n}\n\nalbum_art_extractor_instance_ptr AlbumArtExtractorSpotify::open( file_ptr p_filehint, const char* p_path, abort_callback& p_abort )\n{\n    const auto spotifyObject = SpotifyFilteredTrack::Parse( p_path );\n\n    auto& waBackend = SpotifyInstance::Get().GetWebApi_Backend();\n    auto track = waBackend.GetTrack( spotifyObject.Id(), p_abort );\n    auto artist = waBackend.GetArtist( track->artists[0]->id, p_abort );\n    if ( track->album->images.empty() && artist->images.empty() )\n    {\n        throw exception_album_art_not_found();\n    }\n\n    return ::fb2k::service_new<AlbumArtExtractorInstanceSpotify>( std::move( track ), std::move( artist ) );\n}\n\n} // namespace\n\nnamespace\n{\nstatic service_factory_single_t<AlbumArtExtractorSpotify> g_album_art_extractor;\n}\n"
  },
  {
    "path": "foo_spotify/fb2k/config.cpp",
    "content": "#include <stdafx.h>\n\n#include \"config.h\"\n\nnamespace sptf::config\n{\n\nqwr::fb2k::ConfigBool_MT enable_normalization( sptf::guid::config_enable_normalization, true );\nqwr::fb2k::ConfigBool_MT enable_private_mode( sptf::guid::config_enable_private_mode, false );\nqwr::fb2k::ConfigUint8_MT libspotify_cache_size_in_percent( sptf::guid::config_libspotify_cache_size_in_percent, 10 );\nqwr::fb2k::ConfigUint32_MT libspotify_cache_size_in_mb( sptf::guid::config_libspotify_cache_size_in_mb, 2048 );\nqwr::fb2k::ConfigUint8Enum_MT<BitrateSettings> preferred_bitrate( sptf::guid::config_preferred_bitrate, BitrateSettings::Bitrate320k );\nqwr::fb2k::ConfigString_MT webapi_auth_scopes( sptf::guid::config_webapi_auth_scopes, \"playlist-read-collaborative playlist-read-private user-read-private\" );\n\n} // namespace sptf::config\n"
  },
  {
    "path": "foo_spotify/fb2k/config.h",
    "content": "#pragma once\n\n#include <qwr/fb2k_config.h>\n\nnamespace sptf::config\n{\n\nenum class BitrateSettings : uint8_t\n{ // values are the same as in libspotify's sp_bitrate\n    Bitrate160k = 0,\n    Bitrate320k = 1,\n    Bitrate96k = 2\n};\n\nextern qwr::fb2k::ConfigBool_MT enable_normalization;\nextern qwr::fb2k::ConfigBool_MT enable_private_mode;\nextern qwr::fb2k::ConfigUint8_MT libspotify_cache_size_in_percent;\nextern qwr::fb2k::ConfigUint32_MT libspotify_cache_size_in_mb;\nextern qwr::fb2k::ConfigUint8Enum_MT<BitrateSettings> preferred_bitrate;\nextern qwr::fb2k::ConfigString_MT webapi_auth_scopes;\n\n} // namespace sptf::config\n"
  },
  {
    "path": "foo_spotify/fb2k/file_info_filler.cpp",
    "content": "#include <stdafx.h>\n\n#include \"file_info_filler.h\"\n\n#include <qwr/string_helpers.h>\n\nnamespace\n{\n\nvoid FillMetaInfo( const std::unordered_multimap<std::string, std::string>& meta, file_info& info )\n{\n    auto addMeta = [&]( file_info& info, std::string_view metaName ) {\n        const auto er = meta.equal_range( std::string( metaName.begin(), metaName.end() ) );\n        if ( er.first != er.second )\n        {\n            const auto [key, val] = *er.first;\n            info.meta_add( metaName.data(), val.c_str() );\n        }\n    };\n    auto addMetaIfPositive = [&]( file_info& info, std::string_view metaName ) {\n        const auto er = meta.equal_range( std::string( metaName.begin(), metaName.end() ) );\n        if ( er.first != er.second )\n        {\n            const auto [key, val] = *er.first;\n            auto numOpt = qwr::string::GetNumber<uint32_t>( static_cast<std::string_view>( val ) );\n            if ( numOpt && *numOpt )\n            {\n                info.meta_add( metaName.data(), val.c_str() );\n            }\n        }\n    };\n    auto addMetaMultiple = [&]( file_info& info, std::string_view metaName ) {\n        const auto er = meta.equal_range( std::string( metaName.begin(), metaName.end() ) );\n        for ( auto it = er.first; it != er.second; ++it )\n        {\n            const auto [key, val] = *it;\n            info.meta_add( metaName.data(), val.c_str() );\n        }\n    };\n\n    addMeta( info, \"TITLE\" );\n    addMeta( info, \"ALBUM\" );\n    addMeta( info, \"DATE\" );\n    addMetaMultiple( info, \"ARTIST\" );\n    addMetaMultiple( info, \"ALBUM ARTIST\" );\n    addMetaIfPositive( info, \"TRACKNUMBER\" );\n    addMetaIfPositive( info, \"DISCNUMBER\" );\n\n    const auto er = meta.equal_range( \"SPTF_LENGTH\" );\n    if ( er.first != er.second )\n    {\n        const auto [key, val] = *er.first;\n        auto numOpt = qwr::string::GetNumber<uint32_t>( static_cast<std::string_view>( val ) );\n        if ( numOpt && *numOpt )\n        {\n            info.set_length( *numOpt / 1000.0 );\n        }\n    }\n}\n\nvoid FillTechnicalInfo( const std::unordered_multimap<std::string, std::string>& meta, file_info& info )\n{\n    if ( pfc_infinite == info.info_find( \"codec\" ) )\n    {\n        info.info_set( \"codec\", \"Vorbis\" );\n    }\n}\n\n} // namespace\n\nnamespace sptf::fb2k\n{\n\nvoid FillFileInfoWithMeta( const std::unordered_multimap<std::string, std::string>& meta, file_info& info )\n{\n    FillMetaInfo( meta, info );\n    FillTechnicalInfo( meta, info );\n}\n\n} // namespace sptf::fb2k\n"
  },
  {
    "path": "foo_spotify/fb2k/file_info_filler.h",
    "content": "#pragma once\n\n#include <string>\n#include <unordered_map>\n\nnamespace sptf::fb2k\n{\n\nvoid FillFileInfoWithMeta( const std::unordered_multimap<std::string, std::string>& meta, file_info& info );\n\n}"
  },
  {
    "path": "foo_spotify/fb2k/filesystem.cpp",
    "content": "#include <stdafx.h>\n\n#include <backend/spotify_object.h>\n\nusing namespace std::literals::string_view_literals;\n\nusing namespace sptf;\n\nnamespace\n{\n\nclass FilesystemSpotify : public foobar2000_io::filesystem\n{\npublic:\n    bool get_canonical_path( const char* p_path, pfc::string_base& p_out ) override;\n\n    bool is_our_path( const char* p_path ) override;\n    bool get_display_path( const char* p_path, pfc::string_base& p_out ) override;\n\n    void open( service_ptr_t<file>& p_out, const char* p_path, t_open_mode p_mode, abort_callback& p_abort ) override;\n\n    void remove( const char* p_path, abort_callback& p_abort ) override;\n    //! Moves/renames a file. Will fail if the destination file already exists. \\n\n    //! Note that this function may throw exception_io_denied instead of exception_io_sharing_violation when the file is momentarily in use, due to bugs in Windows MoveFile() API. There is no legitimate way for us to distinguish between the two scenarios.\n    void move( const char* p_src, const char* p_dst, abort_callback& p_abort ) override;\n    //! Queries whether a file at specified path belonging to this filesystem is a remote object or not.\n    bool is_remote( const char* p_src ) override;\n\n    //! Retrieves stats of a file at specified path.\n    void get_stats( const char* p_path, t_filestats& p_stats, bool& p_is_writeable, abort_callback& p_abort ) override;\n\n    //! Creates a directory.\n    void create_directory( const char* p_path, abort_callback& p_abort ) override;\n    void list_directory( const char* p_path, directory_callback& p_out, abort_callback& p_abort ) override;\n\n    //! Hint; returns whether this filesystem supports mime types. \\n\n    //! When this returns false, all file::get_content_type() calls on files opened thru this filesystem implementation will return false; otherwise, file::get_content_type() calls may return true depending on the file.\n    bool supports_content_types() override;\n    ;\n};\n\n} // namespace\n\nnamespace\n{\n\nbool FilesystemSpotify::get_canonical_path( const char* p_path, pfc::string_base& p_out )\n{\n    if ( !SpotifyFilteredTrack::IsValid( p_path, true ) )\n    {\n        return false;\n    }\n\n    try\n    {\n        const auto ret = SpotifyObject( p_path ).ToSchema();\n        p_out = ret.c_str();\n        return true;\n    }\n    catch ( qwr::QwrException& )\n    {\n        return false;\n    }\n}\n\nbool FilesystemSpotify::is_our_path( const char* p_path )\n{\n    // accept only filtered input\n    return SpotifyFilteredTrack::IsValid( p_path, true );\n}\n\nbool FilesystemSpotify::get_display_path( const char* p_path, pfc::string_base& p_out )\n{\n    if ( !SpotifyFilteredTrack::IsValid( p_path, true ) )\n    {\n        return false;\n    }\n\n    try\n    {\n        const auto ret = SpotifyObject( p_path ).ToUri();\n        p_out = ret.c_str();\n        return true;\n    }\n    catch ( qwr::QwrException& )\n    {\n        return false;\n    }\n}\n\nvoid FilesystemSpotify::open( service_ptr_t<file>& p_out, const char* p_path, t_open_mode p_mode, abort_callback& p_abort )\n{\n    (void)p_abort;\n\n    if ( p_mode != open_mode_read )\n    {\n        throw pfc::exception( \"Can't modify remote files\" );\n    }\n\n    p_out = ::fb2k::service_new<file_streamstub>();\n}\n\nvoid FilesystemSpotify::remove( const char* p_path, abort_callback& p_abort )\n{\n    (void)p_path;\n    (void)p_abort;\n    throw pfc::exception( \"Can't delete remote files\" );\n}\n\nvoid FilesystemSpotify::move( const char* p_src, const char* p_dst, abort_callback& p_abort )\n{\n    (void)p_src;\n    (void)p_dst;\n    (void)p_abort;\n    throw pfc::exception( \"Can't move remote files\" );\n}\n\nbool FilesystemSpotify::is_remote( const char* p_src )\n{\n    (void)p_src;\n    return false;\n}\n\nvoid FilesystemSpotify::get_stats( const char* p_path, t_filestats& p_stats, bool& p_is_writeable, abort_callback& p_abort )\n{\n    (void)p_abort;\n    p_stats = filestats_invalid;\n    p_is_writeable = false;\n}\n\nvoid FilesystemSpotify::create_directory( const char* p_path, abort_callback& p_abort )\n{\n    (void)p_path;\n    (void)p_abort;\n    throw pfc::exception( \"Directories are not supported\" );\n}\n\nvoid FilesystemSpotify::list_directory( const char* p_path, directory_callback& p_out, abort_callback& p_abort )\n{\n    (void)p_path;\n    (void)p_out;\n    (void)p_abort;\n    throw pfc::exception( \"Directories are not supported\" );\n}\n\nbool FilesystemSpotify::supports_content_types()\n{\n    return false;\n}\n\n} // namespace\n\nnamespace\n{\n\nstatic service_factory_single_t<FilesystemSpotify> g_filesystem;\n\n}"
  },
  {
    "path": "foo_spotify/fb2k/input.cpp",
    "content": "#include <stdafx.h>\n\n#include <backend/libspotify_backend.h>\n#include <backend/libspotify_wrapper.h>\n#include <backend/spotify_instance.h>\n#include <backend/spotify_object.h>\n#include <backend/webapi_backend.h>\n#include <backend/webapi_objects/webapi_media_objects.h>\n#include <fb2k/config.h>\n#include <fb2k/file_info_filler.h>\n\n#include <qwr/string_helpers.h>\n\n#include <cstdint>\n#include <cstdlib>\n#include <fstream>\n#include <functional>\n#include <vector>\n\nusing namespace std::literals::string_view_literals;\nusing namespace sptf;\n\nnamespace\n{\n\n// input_impl::input_impl\nclass InputSpotify\n    : public input_stubs\n    , public LibSpotify_BackendUser\n{\npublic:\n    InputSpotify() = default;\n    ~InputSpotify();\n\n    // SpotifyBackendUser\n    void Finalize() override;\n\n    // input_impl::open\n    void open( service_ptr_t<file> m_file, const char* p_path, t_input_open_reason p_reason, abort_callback& p_abort );\n\n    // input_info_reader::get_info\n    void get_info( t_int32 subsong, file_info& p_info, abort_callback& p_abort );\n\n    // input_info_reader::get_file_stats\n    t_filestats get_file_stats( abort_callback& p_abort );\n\n    // input_decoder::initialize\n    void decode_initialize( t_int32 subsong, unsigned p_flags, abort_callback& p_abort );\n\n    // input_decoder::run\n    bool decode_run( audio_chunk& p_chunk, abort_callback& p_abort );\n\n    // input_decoder::seek\n    void decode_seek( double p_seconds, abort_callback& p_abort );\n\n    // input_decoder::can_seek\n    bool decode_can_seek();\n\n    // input_decoder::get_dynamic_info\n    bool decode_get_dynamic_info( file_info& p_out, double& p_timestamp_delta );\n\n    // input_decoder::get_dynamic_info_track\n    bool decode_get_dynamic_info_track( file_info& p_out, double& p_timestamp_delta );\n\n    // input_decoder::on_idle\n    void decode_on_idle( abort_callback& p_abort );\n\n    // input_impl::retag_set_info\n    void retag_set_info( t_int32 subsong, const file_info& p_info, abort_callback& p_abort );\n\n    // input_impl::retag_commit\n    void retag_commit( abort_callback& p_abort );\n\n    // input_info_reader::get_subsong_count\n    t_uint32 get_subsong_count();\n\n    // input_info_reader::get_subsong\n    t_uint32 get_subsong( unsigned song );\n\n    // input_entry::is_our_content_type\n    static bool g_is_our_content_type( const char* p_content_type );\n\n    // input_entry::is_our_path\n    static bool g_is_our_path( const char* p_full_path, const char* p_extension );\n\n    // input_entry::get_guid\n    static GUID g_get_guid();\n\n    // input_entry::get_name\n    static const char* g_get_name();\n\nprivate:\n    LibSpotify_Backend& GetInitializedLibSpotify();\n\nprivate:\n    bool usingLibSpotify_ = false;\n    bool hasDecoder_ = false;\n\n    std::optional<t_input_open_reason> openedReason_;\n\n    wrapper::Ptr<sp_track> track_;\n    std::string trackId_;\n    std::unordered_multimap<std::string, std::string> trackMeta_;\n\n    bool isFirstBlock_ = false;\n    int channels_{};\n    int sampleRate_{};\n    int bitRate_{};\n};\n} // namespace\n\nnamespace\n{\n\nstd::string GetPlaybackErrorMessage( sp_error sp, const std::string& trackId, abort_callback& p_abort )\n{\n    if ( sp == SP_ERROR_TRACK_NOT_PLAYABLE )\n    {\n        try\n        {\n            auto& waBackend = SpotifyInstance::Get().GetWebApi_Backend();\n            const auto track = waBackend.GetTrack( trackId, p_abort, true );\n            if ( track->restrictions )\n            {\n                const auto& reason = track->restrictions.value()->reason;\n                if ( reason == \"market\"sv )\n                {\n                    return \"track is not accessible in your country\";\n                }\n                else if ( reason == \"product\"sv )\n                {\n                    return \"track is not accessible for your subscription type\";\n                }\n                else if ( reason == \"explicit\"sv )\n                {\n                    return \"track is explicit and your account is set to not play explicit content\";\n                }\n                else\n                {\n                    return reason;\n                }\n            }\n        }\n        catch ( const std::exception& )\n        {\n        }\n    }\n\n    return sp_error_message( sp );\n}\n\n} // namespace\n\nnamespace\n{\n\nInputSpotify::~InputSpotify()\n{\n    try\n    {\n        Finalize();\n    }\n    catch ( const std::exception& )\n    {\n    }\n}\n\nvoid InputSpotify::Finalize()\n{\n    if ( !usingLibSpotify_ )\n    {\n        return;\n    }\n    usingLibSpotify_ = false;\n\n    auto& lsBackend = SpotifyInstance::Get().GetLibSpotify_Backend();\n    {\n        if ( hasDecoder_ )\n        {\n            lsBackend.ReleaseDecoder( this );\n        }\n    }\n\n    if ( track_ )\n    {\n        lsBackend.ExecSpMutex( [&] {\n            track_.Release();\n        } );\n    }\n\n    lsBackend.UnregisterBackendUser( *this );\n}\n\nvoid InputSpotify::open( service_ptr_t<file> m_file, const char* p_path, t_input_open_reason p_reason, abort_callback& p_abort )\n{\n    openedReason_ = p_reason;\n\n    if ( p_reason == input_open_info_write )\n    {\n        throw exception_io_denied_readonly();\n    }\n\n    auto& waBackend = SpotifyInstance::Get().GetWebApi_Backend();\n\n    const auto spotifyObject = SpotifyFilteredTrack::Parse( p_path );\n    trackId_ = spotifyObject.Id();\n    const auto track = waBackend.GetTrack( trackId_, p_abort );\n    trackMeta_ = waBackend.GetMetaForTracks( nonstd::span<const std::unique_ptr<const WebApi_Track>>( &track, 1 ) )[0];\n\n    if ( p_reason == input_open_info_read )\n    { // don't use LibSpotify stuff if it's not needed\n        return;\n    }\n\n    auto& lsBackend = GetInitializedLibSpotify();\n\n    auto pSession = lsBackend.GetInitializedSpSession( p_abort );\n\n    lsBackend.ExecSpMutex( [&] {\n        wrapper::Ptr<sp_link> link( sp_link_create_from_string( spotifyObject.ToUri().c_str() ) );\n        if ( !link )\n        {\n            throw exception_io_data( \"Couldn't parse url\" );\n        }\n\n        track_.Release();\n\n        switch ( sp_link_type( link ) )\n        {\n        case SP_LINKTYPE_TRACK:\n        {\n            track_ = sp_link_as_track( link );\n            break;\n        }\n        default:\n        {\n            throw exception_io_data( \"Only track links should be passed to input\" );\n        }\n        }\n    } );\n\n    while ( true )\n    {\n        // TODO: clean up here\n        const auto done = lsBackend.ExecSpMutex( [&] {\n            const auto sp = sp_track_error( track_ );\n            if ( SP_ERROR_OK == sp )\n            {\n                return true;\n            }\n            else if ( SP_ERROR_IS_LOADING == sp )\n            {\n                return false;\n            }\n            else\n            {\n                throw qwr::QwrException( fmt::format( \"sp_track_error failed: {}\", sp_error_message( sp ) ) );\n            }\n        } );\n\n        if ( done )\n        {\n            break;\n        }\n\n        p_abort.sleep( 0.05 );\n    }\n\n    bitRate_ = [] {\n        switch ( config::preferred_bitrate )\n        {\n        case config::BitrateSettings::Bitrate96k:\n        {\n            return 96;\n        }\n        case config::BitrateSettings::Bitrate160k:\n        {\n            return 160;\n        }\n        case config::BitrateSettings::Bitrate320k:\n        {\n            return 320;\n        }\n        default:\n        {\n            assert( false );\n            return 320;\n        }\n        }\n    }();\n}\n\nvoid InputSpotify::get_info( t_int32 subsong, file_info& p_info, abort_callback& p_abort )\n{\n    if ( subsong )\n    {\n        throw std::exception( \"This track does not have any sub-songs\" );\n    }\n\n    sptf::fb2k::FillFileInfoWithMeta( trackMeta_, p_info );\n    if ( openedReason_ == input_open_decode )\n    { // Use exact length when possible\n        auto& lsBackend = GetInitializedLibSpotify();\n        lsBackend.ExecSpMutex( [&] {\n            p_info.set_length( sp_track_duration( track_ ) / 1000.0 );\n        } );\n    }\n}\n\nfoobar2000_io::t_filestats InputSpotify::get_file_stats( abort_callback& p_abort )\n{\n    return t_filestats{};\n}\n\nvoid InputSpotify::decode_initialize( t_int32 subsong, unsigned p_flags, abort_callback& p_abort )\n{\n    isFirstBlock_ = true;\n\n    if ( subsong )\n    {\n        throw std::exception( \"This track does not have any sub-songs\" );\n    }\n\n    if ( !( p_flags & input_flag_playback ) )\n    {\n        throw exception_io_denied();\n    }\n\n    auto& lsBackend = GetInitializedLibSpotify();\n    lsBackend.AcquireDecoder( this );\n    hasDecoder_ = true;\n\n    lsBackend.GetAudioBuffer().clear();\n    auto pSession = lsBackend.GetInitializedSpSession( p_abort );\n\n    lsBackend.ExecSpMutex( [&] {\n        const auto sp = sp_session_player_load( pSession, track_ );\n        if ( sp != SP_ERROR_OK )\n        {\n            throw qwr::QwrException( fmt::format( \"sp_session_player_load failed: {}\", GetPlaybackErrorMessage( sp, trackId_, p_abort ) ) );\n        }\n\n        sp_session_player_play( pSession, true );\n    } );\n}\n\nbool InputSpotify::decode_run( audio_chunk& p_chunk, abort_callback& p_abort )\n{\n    bool isEof = false;\n    const auto dataReader = [&]( const AudioBuffer::AudioChunkHeader& header,\n                                 const uint16_t* data ) {\n        if ( header.eof )\n        {\n            isEof = true;\n            return;\n        }\n        channels_ = header.channels;\n        sampleRate_ = header.sampleRate;\n        p_chunk.set_data_fixedpoint( data,\n                                     header.size * sizeof( uint16_t ),\n                                     header.sampleRate,\n                                     header.channels,\n                                     16,\n                                     audio_chunk::channel_config_stereo );\n    };\n\n    auto& lsBackend = GetInitializedLibSpotify();\n    auto& buf = lsBackend.GetAudioBuffer();\n\n    if ( !buf.read( dataReader ) )\n    {\n        buf.wait_for_data( p_abort );\n        if ( !buf.read( dataReader ) )\n        { // wait was aborted, ending playback\n            isEof = true;\n        }\n    }\n\n    if ( isEof )\n    {\n        lsBackend.ReleaseDecoder( this );\n        hasDecoder_ = false;\n        return false;\n    }\n\n    return true;\n}\n\nvoid InputSpotify::decode_seek( double p_seconds, abort_callback& p_abort )\n{\n    isFirstBlock_ = true;\n\n    auto& lsBackend = GetInitializedLibSpotify();\n    lsBackend.GetAudioBuffer().clear();\n    auto pSession = lsBackend.GetInitializedSpSession( p_abort );\n    lsBackend.ExecSpMutex( [&] {\n        sp_session_player_seek( pSession, static_cast<int>( p_seconds * 1000 ) );\n    } );\n}\n\nbool InputSpotify::decode_can_seek()\n{\n    return true;\n}\n\nbool InputSpotify::decode_get_dynamic_info( file_info& p_out, double& p_timestamp_delta )\n{\n    if ( !isFirstBlock_ )\n    {\n        return false;\n    }\n\n    p_out.info_set_int( \"CHANNELS\", channels_ );\n    p_out.info_set_int( \"SAMPLERATE\", sampleRate_ );\n    p_out.info_set_bitrate( bitRate_ );\n\n    isFirstBlock_ = false;\n\n    return true;\n}\n\nbool InputSpotify::decode_get_dynamic_info_track( file_info& p_out, double& p_timestamp_delta )\n{\n    return false;\n}\n\nvoid InputSpotify::decode_on_idle( abort_callback& p_abort )\n{\n    (void)p_abort;\n}\n\nvoid InputSpotify::retag_set_info( t_int32 subsong, const file_info& p_info, abort_callback& p_abort )\n{\n    throw exception_io_data();\n}\n\nvoid InputSpotify::retag_commit( abort_callback& p_abort )\n{\n    throw exception_io_data();\n}\n\nbool InputSpotify::g_is_our_content_type( const char* p_content_type )\n{\n    return false;\n}\n\nbool InputSpotify::g_is_our_path( const char* p_full_path, const char* p_extension )\n{\n    (void)p_extension;\n    // accept only filtered input\n    return SpotifyFilteredTrack::IsValid( p_full_path, false );\n}\n\nt_uint32 InputSpotify::get_subsong_count()\n{\n    return 1;\n}\n\nt_uint32 InputSpotify::get_subsong( unsigned song )\n{\n    return song;\n}\n\nGUID InputSpotify::g_get_guid()\n{\n    return guid::input;\n}\n\nconst char* InputSpotify::g_get_name()\n{\n    return SPTF_NAME \": decoder\";\n}\n\nLibSpotify_Backend& InputSpotify::GetInitializedLibSpotify()\n{\n    auto& lsBackend = SpotifyInstance::Get().GetLibSpotify_Backend();\n    if ( !usingLibSpotify_ )\n    {\n        lsBackend.RegisterBackendUser( *this );\n        usingLibSpotify_ = true;\n    }\n    return lsBackend;\n}\n\n} // namespace\n\nnamespace\n{\n\ninput_factory_t<InputSpotify> g_input;\n\n} // namespace\n"
  },
  {
    "path": "foo_spotify/fb2k/playback.cpp",
    "content": "#include <stdafx.h>\n\n#include \"playback.h\"\n\n#include <backend/libspotify_backend.h>\n\nnamespace sptf::fb2k\n{\n\nstd::mutex PlayCallbacks::mutex_;\nLibSpotify_Backend* PlayCallbacks::pLsBackend_ = nullptr;\n\nPlayCallbacks::PlayCallbacks()\n{\n}\n\nPlayCallbacks::~PlayCallbacks()\n{\n}\n\nvoid PlayCallbacks::Initialize( LibSpotify_Backend& lsBackend )\n{\n    std::lock_guard lg( mutex_ );\n    pLsBackend_ = &lsBackend;\n}\n\nvoid PlayCallbacks::Finalize()\n{\n    std::lock_guard lg( mutex_ );\n    pLsBackend_ = nullptr;\n}\n\nunsigned PlayCallbacks::get_flags()\n{\n    return ( flag_on_playback_stop | flag_on_playback_pause );\n}\n\nvoid PlayCallbacks::on_playback_pause( bool isPaused )\n{\n    std::lock_guard lg( mutex_ );\n\n    if ( !pLsBackend_ )\n    {\n        return;\n    }\n\n    auto pSession = pLsBackend_->GetWhateverSpSession();\n    pLsBackend_->ExecSpMutex( [&] {\n        sp_session_player_play( pSession, !isPaused );\n    } );\n}\n\nvoid PlayCallbacks::on_playback_stop( play_control::t_stop_reason reason )\n{\n    if ( play_control::stop_reason_starting_another == reason )\n    {\n        return;\n    }\n\n    std::lock_guard lg( mutex_ );\n\n    if ( !pLsBackend_ )\n    {\n        return;\n    }\n\n    auto pSession = pLsBackend_->GetWhateverSpSession();\n    pLsBackend_->ExecSpMutex( [&] {\n        sp_session_player_unload( pSession );\n    } );\n}\n\n} // namespace sptf::fb2k\n\nnamespace\n{\n\nplay_callback_static_factory_t<sptf::fb2k::PlayCallbacks> g_play_callback_static;\n\n}\n"
  },
  {
    "path": "foo_spotify/fb2k/playback.h",
    "content": "#pragma once\n\n#include <mutex>\n\nnamespace sptf\n{\n\nclass LibSpotify_Backend;\n\n}\n\nnamespace sptf::fb2k\n{\n\nclass PlayCallbacks\n    : public play_callback_static\n{\npublic:\n    PlayCallbacks();\n    ~PlayCallbacks();\n\n    static void Initialize( LibSpotify_Backend& lsBackend );\n    static void Finalize();\n\n    // play_callback_static\n    unsigned get_flags() override;\n    void on_playback_pause( bool isPaused ) override;\n    void on_playback_stop( play_control::t_stop_reason reason ) override;\n\n    void on_playback_starting( play_control::t_track_command p_command, bool p_paused ) override{};\n    void on_playback_new_track( metadb_handle_ptr p_track ) override{};\n    void on_playback_seek( double p_time ) override{};\n    void on_playback_edited( metadb_handle_ptr p_track ) override{};\n    void on_playback_dynamic_info( const file_info& p_info ) override{};\n    void on_playback_dynamic_info_track( const file_info& p_info ) override{};\n    void on_playback_time( double p_time ) override{};\n    void on_volume_change( float p_new_val ) override{};\n\nprivate:\n    static std::mutex mutex_;\n    static LibSpotify_Backend* pLsBackend_;\n};\n\n} // namespace sptf::fb2k\n"
  },
  {
    "path": "foo_spotify/fb2k/playlist.cpp",
    "content": "#include <stdafx.h>\n\n#include <backend/spotify_instance.h>\n#include <backend/spotify_object.h>\n#include <backend/webapi_backend.h>\n#include <backend/webapi_objects/webapi_media_objects.h>\n\n#include <qwr/abort_callback.h>\n#include <qwr/thread_pool.h>\n\nusing namespace sptf;\n\nnamespace\n{\n\nclass PlaylistCallbackSpotify : public playlist_callback_static\n{\npublic:\n    unsigned get_flags() override;\n    void on_default_format_changed() override\n    {\n    }\n    void on_item_ensure_visible( t_size p_playlist, t_size p_idx ) override\n    {\n    }\n    void on_item_focus_change( t_size p_playlist, t_size p_from, t_size p_to ) override\n    {\n    }\n    void on_items_added( t_size p_playlist, t_size p_start, metadb_handle_list_cref p_data, const pfc::bit_array& p_selection ) override\n    {\n    }\n    void on_items_removing( t_size p_playlist, const pfc::bit_array& p_mask, t_size p_old_count, t_size p_new_count ) override\n    {\n    }\n    void on_items_removed( t_size p_playlist, const pfc::bit_array& p_mask, t_size p_old_count, t_size p_new_count ) override\n    {\n    }\n    void on_items_reordered( t_size p_playlist, const t_size* p_order, t_size p_count ) override\n    {\n    }\n    void on_items_replaced( t_size p_playlist, const pfc::bit_array& p_mask, const pfc::list_base_const_t<t_on_items_replaced_entry>& p_data ) override\n    {\n    }\n    void on_items_selection_change( t_size p_playlist, const pfc::bit_array& p_affected, const pfc::bit_array& p_state ) override\n    {\n    }\n    void on_items_modified( t_size p_playlist, const pfc::bit_array& p_mask ) override\n    {\n    }\n    void on_items_modified_fromplayback( t_size p_playlist, const pfc::bit_array& p_mask, play_control::t_display_level p_level ) override\n    {\n    }\n    void on_playback_order_changed( t_size p_new_index ) override\n    {\n    }\n    void on_playlist_activate( t_size p_old, t_size p_new ) override;\n    void on_playlist_created( t_size p_index, const char* p_name, t_size p_name_len ) override\n    {\n    }\n    void on_playlist_locked( t_size p_playlist, bool p_locked ) override\n    {\n    }\n    void on_playlist_renamed( t_size p_index, const char* p_new_name, t_size p_new_name_len ) override\n    {\n    }\n    void on_playlists_removing( const pfc::bit_array& p_mask, t_size p_old_count, t_size p_new_count ) override\n    {\n    }\n    void on_playlists_removed( const pfc::bit_array& p_mask, t_size p_old_count, t_size p_new_count ) override\n    {\n    }\n    void on_playlists_reorder( const t_size* p_order, t_size p_count ) override\n    {\n    }\n};\n\n} // namespace\n\nnamespace\n{\n\nunsigned PlaylistCallbackSpotify::get_flags()\n{\n    return flag_on_playlist_activate;\n}\n\nvoid PlaylistCallbackSpotify::on_playlist_activate( t_size p_old, t_size p_new )\n{\n    if ( p_old == p_new )\n    {\n        return;\n    }\n\n    metadb_handle_list items;\n    playlist_manager::get()->playlist_get_all_items( p_new, items );\n\n    std::vector<std::string> trackIds;\n    for ( const auto& pMeta: qwr::pfc_x::Make_Stl_CRef( items ) )\n    {\n        const char* path = pMeta->get_location().get_path();\n        if ( !SpotifyFilteredTrack::IsValid( path, false ) )\n        {\n            continue;\n        }\n        trackIds.emplace_back( SpotifyFilteredTrack::Parse( path ).Id() );\n    }\n\n    if ( trackIds.empty() )\n    {\n        return;\n    }\n\n    auto& threadPool = SpotifyInstance::Get().GetThreadPool();\n    threadPool.AddTask( [trackIds = std::move( trackIds )] {\n        try\n        {\n            auto& waBackend = SpotifyInstance::Get().GetWebApi_Backend();\n\n            // pre-cache tracks\n            qwr::TimedAbortCallback tac1;\n            const auto tracks = waBackend.GetTracks( trackIds, tac1 );\n\n            const auto artistIds =\n                tracks\n                | ranges::views::transform( []( const auto& pTrack ) -> std::string { return pTrack->artists[0]->id; } )\n                | ranges::to_vector;\n\n            // pre-cache artists\n            qwr::TimedAbortCallback tac2;\n            waBackend.RefreshCacheForArtists( artistIds, tac2 );\n        }\n        catch ( const std::exception& e )\n        {\n            FB2K_console_formatter() << SPTF_UNDERSCORE_NAME \" (error):\\n\"\n                                     << \"Failed to refresh tracks:\\n\"\n                                     << e.what();\n        }\n    } );\n}\n\n} // namespace\n\nnamespace\n{\n\nservice_factory_single_t<PlaylistCallbackSpotify> g_playlist_callback_static;\n\n}\n"
  },
  {
    "path": "foo_spotify/fb2k/playlist_loader.cpp",
    "content": "#include <stdafx.h>\n\n#include <backend/spotify_instance.h>\n#include <backend/spotify_object.h>\n#include <backend/webapi_backend.h>\n#include <backend/webapi_objects/webapi_media_objects.h>\n#include <fb2k/file_info_filler.h>\n\n#include <qwr/error_popup.h>\n#include <qwr/string_helpers.h>\n\nusing namespace std::literals::string_view_literals;\n\nusing namespace sptf;\n\nnamespace\n{\n\nclass PlaylistLoaderSpotify : public playlist_loader\n{\npublic:\n    PlaylistLoaderSpotify() = default;\n\npublic:\n    // playlist_loader\n\n    //! Parses specified playlist file into list of playable locations. Throws exception_io or derivatives on failure, exception_aborted on abort. If specified file is not a recognized playlist file, exception_io_unsupported_format is thrown.\n    //! @param p_path Path of playlist file to parse. Used for relative path handling purposes (p_file parameter is used for actual file access).\n    //! @param p_file File interface to use for reading. Read/write pointer must be set to beginning by caller before calling.\n    //! @param p_callback Callback object receiving enumerated playable item locations.\n    void open( const char* p_path, const service_ptr_t<file>& p_file, playlist_loader_callback::ptr p_callback, abort_callback& p_abort ) override;\n    //! Writes a playlist file containing specific item list to specified file. Will fail (pfc::exception_not_implemented) if specified playlist_loader is read-only (can_write() returns false).\n    //! @param p_path Path of playlist file to write. Used for relative path handling purposes (p_file parameter is used for actual file access).\n    //! @param p_file File interface to use for writing. Caller should ensure that the file is empty (0 bytes long) before calling.\n    //! @param p_data List of items to save to playlist file.\n    //! @param p_abort abort_callback object signaling user aborting the operation. Note that aborting a save playlist operation will most likely leave user with corrupted/incomplete file.\n    void write( const char* p_path, const service_ptr_t<file>& p_file, metadb_handle_list_cref p_data, abort_callback& p_abort ) override;\n    //! Returns extension of file format handled by this playlist_loader implementation (a UTF-8 encoded null-terminated string).\n    const char* get_extension() override;\n    //! Returns whether this playlist_loader implementation supports writing. If can_write() returns false, all write() calls will fail.\n    bool can_write() override;\n    //! Returns whether specified content type is one of playlist types supported by this playlist_loader implementation or not.\n    //! @param p_content_type Content type to query, a UTF-8 encoded null-terminated string.\n    bool is_our_content_type( const char* p_content_type ) override;\n    //! Returns whether playlist format extension supported by this implementation should be listed on file types associations page.\n    bool is_associatable() override;\n\n    /*\n    //! Attempts to load a playlist file from specified filesystem path. Throws exception_io or derivatives on failure, exception_aborted on abort. If specified file is not a recognized playlist file, exception_io_unsupported_format is thrown. \\n\n    //! Equivalent to g_load_playlist_filehint(NULL,p_path,p_callback).\n    //! @param p_path Filesystem path to load playlist from, a UTF-8 encoded null-terminated string.\n    //! @param p_callback Callback object receiving enumerated playable item locations as well as signaling user aborting the operation.\n    static void g_load_playlist( const char* p_path, playlist_loader_callback::ptr p_callback, abort_callback& p_abort );\n\n    //! Attempts to load a playlist file from specified filesystem path. Throws exception_io or derivatives on failure, exception_aborted on abort. If specified file is not a recognized playlist file, exception_io_unsupported_format is thrown.\n    //! @param p_path Filesystem path to load playlist from, a UTF-8 encoded null-terminated string.\n    //! @param p_callback Callback object receiving enumerated playable item locations as well as signaling user aborting the operation.\n    //! @param fileHint File object to read from, can be NULL if not available.\n    static void g_load_playlist_filehint( file::ptr fileHint, const char* p_path, playlist_loader_callback::ptr p_callback, abort_callback& p_abort );\n\n    //! Attempts to load a playlist file from specified filesystem path. Throws exception_io or derivatives on failure, exception_aborted on abort. If specified file is not a recognized playlist file, returns false; returns true upon successful playlist load.\n    //! @param p_path Filesystem path to load playlist from, a UTF-8 encoded null-terminated string.\n    //! @param p_callback Callback object receiving enumerated playable item locations as well as signaling user aborting the operation.\n    //! @param fileHint File object to read from, can be NULL if not available.\n    static bool g_try_load_playlist( file::ptr fileHint, const char* p_path, playlist_loader_callback::ptr p_callback, abort_callback& p_abort );\n\n    //! Saves specified list of locations into a playlist file. Throws exception_io or derivatives on failure, exception_aborted on abort.\n    //! @param p_path Filesystem path to save playlist to, a UTF-8 encoded null-terminated string.\n    //! @param p_data List of items to save to playlist file.\n    //! @param p_abort abort_callback object signaling user aborting the operation. Note that aborting a save playlist operation will most likely leave user with corrupted/incomplete file.\n    static void g_save_playlist( const char* p_path, metadb_handle_list_cref p_data, abort_callback& p_abort );\n\n    //! Processes specified path to generate list of playable items. Includes recursive directory/archive enumeration. \\n\n    //! Does not touch playlist files encountered - use g_process_path_ex() if specified path is possibly a playlist file; playlist files found inside directories or archives are ignored regardless.\\n\n    //! Warning: caller must handle exceptions which will occur in case of I/O failure.\n    //! @param p_path Filesystem path to process; a UTF-8 encoded null-terminated string.\n    //! @param p_callback Callback object receiving enumerated playable item locations as well as signaling user aborting the operation.\n    //! @param p_type Origin of p_path string. Reserved for internal use in recursive calls, should be left at default value; it controls various internal behaviors.\n    static void g_process_path( const char* p_path, playlist_loader_callback::ptr p_callback, abort_callback& p_abort, playlist_loader_callback::t_entry_type p_type = playlist_loader_callback::entry_user_requested );\n\n    //! Calls attempts to process specified path as a playlist; if that fails (i.e. not a playlist), calls g_process_path with same parameters. See g_process_path for parameter descriptions. \\n\n    //! Warning: caller must handle exceptions which will occur in case of I/O failure or playlist parsing failure.\n    //! @returns True if specified path was processed as a playlist file, false otherwise (relevant in some scenarios where output is sorted after loading, playlist file contents should not be sorted).\n    static bool g_process_path_ex( const char* p_path, playlist_loader_callback::ptr p_callback, abort_callback& p_abort, playlist_loader_callback::t_entry_type p_type = playlist_loader_callback::entry_user_requested );\n    */\n};\n\n} // namespace\n\nnamespace\n{\n\nstruct SkippedTrack\n{\n    std::string name;\n    std::string reason;\n};\n\nstd::vector<SkippedTrack>\nTransformToSkippedTracks( nonstd::span<const std::unique_ptr<const WebApi_LocalTrack>> tracks )\n{\n    return ranges::views::transform( tracks,\n                                     [&]( const auto& pTrack ) -> SkippedTrack {\n                                         return { ( pTrack->name ? *pTrack->name : pTrack->uri ), \"local track\" };\n                                     } )\n           | ranges::to_vector;\n}\n\nstd::tuple<std::vector<std::unique_ptr<const sptf::WebApi_Track>>, std::vector<SkippedTrack>>\nGetTracks( const SpotifyObject spotifyObject, abort_callback& p_abort )\n{\n    auto& waBackend = SpotifyInstance::Get().GetWebApi_Backend();\n\n    const auto preCacheArtists = [&waBackend]( const auto& tracks, auto& p_abort ) {\n        const auto artistIds =\n            tracks\n            | ranges::views::transform( []( const auto& pTrack ) -> std::string { return pTrack->artists[0]->id; } )\n            | ranges::to_vector;\n\n        waBackend.RefreshCacheForArtists( artistIds, p_abort );\n    };\n\n    if ( spotifyObject.type == \"album\" )\n    {\n        auto tracks = waBackend.GetTracksFromAlbum( spotifyObject.id, p_abort );\n        preCacheArtists( tracks, p_abort );\n\n        return { std::move( tracks ), std::vector<SkippedTrack>{} };\n    }\n    else if ( spotifyObject.type == \"playlist\" )\n    {\n        auto [tracks, localTracks] = waBackend.GetTracksFromPlaylist( spotifyObject.id, p_abort );\n        preCacheArtists( tracks, p_abort );\n\n        // ??? Dunno why this is required. Smth to do with structured bindings and RVO.\n        return { std::move( tracks ), TransformToSkippedTracks( localTracks ) };\n    }\n    else if ( spotifyObject.type == \"artist\" )\n    {\n        return { waBackend.GetTopTracksForArtist( spotifyObject.id, p_abort ), std::vector<SkippedTrack>{} };\n    }\n    else if ( spotifyObject.type == \"track\" )\n    {\n        std::vector<std::unique_ptr<const WebApi_Track>> tmp;\n        tmp.emplace_back( waBackend.GetTrack( spotifyObject.id, p_abort ) );\n\n        return { std::move( tmp ), std::vector<SkippedTrack>{} };\n    }\n    else if ( spotifyObject.type == \"local\" )\n    {\n        std::vector<SkippedTrack> tmp;\n        tmp.emplace_back( SkippedTrack{ spotifyObject.id, \"local track\" } );\n\n        return { std::vector<std::unique_ptr<const sptf::WebApi_Track>>{}, tmp };\n    }\n    else\n    {\n        throw qwr::QwrException( \"Unexpected Spotify object type: {}\", spotifyObject.type );\n    }\n}\n\nvoid ReportSkippedTracks( nonstd::span<const SkippedTrack> skippedTracks )\n{\n    if ( skippedTracks.empty() )\n    {\n        return;\n    }\n\n    const auto formatedSkippedTracks = ranges::views::transform( skippedTracks,\n                                                                 [&]( const auto& track ) -> std::string {\n                                                                     return fmt::format( \"{}: {}\", track.name, track.reason );\n                                                                 } )\n                                       | ranges::to_vector;\n    const auto msg = fmt::format( \"Failed to add the following tracks:\\n\"\n                                  \"  {}\\n\",\n                                  fmt::join( formatedSkippedTracks, \"\\n  \" ) );\n\n    qwr::ReportErrorWithPopup( SPTF_UNDERSCORE_NAME, msg );\n}\n\n} // namespace\n\nnamespace\n{\n\nvoid PlaylistLoaderSpotify::open( const char* p_path, const service_ptr_t<file>& p_file, playlist_loader_callback::ptr p_callback, abort_callback& p_abort )\n{\n    const auto spotifyObject = [&] {\n        try\n        {\n            return SpotifyObject( p_path );\n        }\n        catch ( const qwr::QwrException& )\n        {\n            throw exception_io_unsupported_format();\n        }\n    }();\n\n    p_callback->on_progress( p_path );\n\n    auto& waBackend = SpotifyInstance::Get().GetWebApi_Backend();\n\n    auto [tracks, skippedTracks] = GetTracks( spotifyObject, p_abort );\n    std::vector<std::string> relinkedTracks;\n\n    const auto tracksMeta = waBackend.GetMetaForTracks( tracks );\n    for ( const auto& [track, trackMeta]: ranges::views::zip( tracks, tracksMeta ) )\n    {\n        file_info_impl f_info;\n        sptf::fb2k::FillFileInfoWithMeta( trackMeta, f_info );\n\n        metadb_handle_ptr f_handle;\n        p_callback->handle_create( f_handle, make_playable_location( SpotifyFilteredTrack( track->id ).ToSchema().c_str(), 0 ) );\n        p_callback->on_entry_info( f_handle, playlist_loader_callback::entry_user_requested, filestats_invalid, f_info, false );\n    }\n\n    ReportSkippedTracks( skippedTracks );\n}\n\nvoid PlaylistLoaderSpotify::write( const char* p_path, const service_ptr_t<file>& p_file, metadb_handle_list_cref p_data, abort_callback& p_abort )\n{\n    throw pfc::exception_not_implemented();\n}\n\nconst char* PlaylistLoaderSpotify::get_extension()\n{\n    return \"\";\n}\n\nbool PlaylistLoaderSpotify::can_write()\n{\n    return false;\n}\n\nbool PlaylistLoaderSpotify::is_our_content_type( const char* p_content_type )\n{\n    constexpr auto mime = \"text/html; charset=utf-8\"sv;\n    const auto lowerContentType = [&p_content_type]() {\n        // Content type should not contain anything other than ASCII\n        return std::string_view{ p_content_type }\n               | ranges::views::transform( []( auto i ) { return static_cast<char>( ::tolower( i ) ); } )\n               | ranges::to<std::string>;\n    }();\n\n    return ( mime == lowerContentType );\n}\n\nbool PlaylistLoaderSpotify::is_associatable()\n{\n    return false;\n}\n\n} // namespace\n\nnamespace\n{\n\nplaylist_loader_factory_t<PlaylistLoaderSpotify> g_playlist_loader;\n\n} // namespace\n"
  },
  {
    "path": "foo_spotify/foo_spotify.rc",
    "content": "// Microsoft Visual C++ generated resource script.\n//\n#include \"resource.h\"\n\n#define APSTUDIO_READONLY_SYMBOLS\n/////////////////////////////////////////////////////////////////////////////\n//\n// Generated from the TEXTINCLUDE 2 resource.\n//\n#define APSTUDIO_HIDDEN_SYMBOLS\n#include \"windows.h\"\n#undef APSTUDIO_HIDDEN_SYMBOLS\n\n#include <atlres.h>\n#include <component_defines.h>\n\n/////////////////////////////////////////////////////////////////////////////\n#undef APSTUDIO_READONLY_SYMBOLS\n\n/////////////////////////////////////////////////////////////////////////////\n// English (United States) resources\n\n#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)\nLANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US\n#pragma code_page(1252)\n\n/////////////////////////////////////////////////////////////////////////////\n//\n// Dialog\n//\n\nIDD_NOT_AUTH DIALOGEX 0, 0, 249, 78\nSTYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU\nCAPTION \"Dialog\"\nFONT 8, \"MS Shell Dlg\", 400, 0, 0x1\nBEGIN\n    DEFPUSHBUTTON   \"OK\",IDOK,30,56,78,14\n    PUSHBUTTON      \"Authenticate...\",IDC_BTN_OPEN_PREF,141,56,78,14\n    LTEXT           \"Static\",IDC_STATIC_NOT_AUTH,7,7,235,41\nEND\n\nIDD_PREF_TAB_HOST DIALOGEX 0, 0, 334, 288\nSTYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD | WS_CLIPSIBLINGS\nEXSTYLE WS_EX_CONTROLPARENT\nFONT 8, \"MS Shell Dlg\", 400, 0, 0x0\nBEGIN\n    CONTROL         \"Tabs\",IDC_TAB_HOST,\"SysTabControl32\",WS_TABSTOP,0,0,332,287\nEND\n\nIDD_PREF_TAB_AUTH DIALOGEX 0, 0, 327, 268\nSTYLE DS_SETFONT | DS_FIXEDSYS | DS_CONTROL | WS_CHILD\nFONT 8, \"MS Shell Dlg\", 400, 0, 0x0\nBEGIN\n    GROUPBOX        \"LibSpotify\",IDC_STATIC,11,13,282,40\n    PUSHBUTTON      \"LS Login\",IDC_BTN_LOGIN_LIBSPOTIFY,17,28,50,14\n    LTEXT           \"LS status:\",IDC_STATIC_LIBSPOTIFY_STATUS,72,30,217,19\n    GROUPBOX        \"WebAPI\",IDC_STATIC,11,61,282,40\n    PUSHBUTTON      \"WA Login\",IDC_BTN_LOGIN_WEBAPI,17,76,50,14\n    LTEXT           \"WA status:\",IDC_STATIC_WEBAPI_STATUS,72,78,217,19\nEND\n\nIDD_PREF_TAB_PLAYBACK DIALOGEX 0, 0, 327, 268\nSTYLE DS_SETFONT | DS_FIXEDSYS | DS_CONTROL | WS_CHILD\nFONT 8, \"MS Shell Dlg\", 400, 0, 0x0\nBEGIN\n    GROUPBOX        \"Playback\",IDC_STATIC,11,13,285,87\n    LTEXT           \"Prefered bitrate\",IDC_STATIC,22,28,52,8\n    COMBOBOX        IDC_COMBO_BITRATE,22,39,126,30,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP\n    CONTROL         \"Enable volume normalization\",IDC_CHECK_NORMALIZE,\"Button\",BS_AUTOCHECKBOX | WS_TABSTOP,24,62,106,10\n    CONTROL         \"Enable private mode\",IDC_CHECK_PRIVATE,\"Button\",BS_AUTOCHECKBOX | WS_TABSTOP,24,77,81,10\n    GROUPBOX        \"Cache\",IDC_STATIC,11,114,285,99\n    LTEXT           \"Maximum size in MB (0 - disabled)\",IDC_STATIC,29,132,107,8\n    CONTROL         \"\",IDC_SLIDER_CACHE_MB,\"msctls_trackbar32\",TBS_AUTOTICKS | TBS_TOOLTIPS | TBS_NOTIFYBEFOREMOVE | WS_TABSTOP,19,142,148,15\n    EDITTEXT        IDC_EDIT_CACHE_MB,170,141,40,14,ES_AUTOHSCROLL | ES_NUMBER\n    LTEXT           \"Maximum size in % of total free space (0 - disabled)\",IDC_STATIC,29,169,122,8\n    CONTROL         \"\",IDC_SLIDER_CACHE_PERCENT,\"msctls_trackbar32\",TBS_AUTOTICKS | TBS_TOOLTIPS | TBS_NOTIFYBEFOREMOVE | WS_TABSTOP,19,179,148,15\n    EDITTEXT        IDC_EDIT_CACHE_PERCENT,170,178,40,14,ES_AUTOHSCROLL | ES_NUMBER\nEND\n\n\n/////////////////////////////////////////////////////////////////////////////\n//\n// DESIGNINFO\n//\n\n#ifdef APSTUDIO_INVOKED\nGUIDELINES DESIGNINFO\nBEGIN\n    IDD_NOT_AUTH, DIALOG\n    BEGIN\n        LEFTMARGIN, 7\n        RIGHTMARGIN, 242\n        TOPMARGIN, 7\n        BOTTOMMARGIN, 70\n    END\n\n    IDD_PREF_TAB_HOST, DIALOG\n    BEGIN\n    END\n\n    IDD_PREF_TAB_AUTH, DIALOG\n    BEGIN\n    END\n\n    IDD_PREF_TAB_PLAYBACK, DIALOG\n    BEGIN\n    END\nEND\n#endif    // APSTUDIO_INVOKED\n\n\n/////////////////////////////////////////////////////////////////////////////\n//\n// AFX_DIALOG_LAYOUT\n//\n\nIDD_PREF_TAB_HOST AFX_DIALOG_LAYOUT\nBEGIN\n    0\nEND\n\nIDD_NOT_AUTH AFX_DIALOG_LAYOUT\nBEGIN\n    0\nEND\n\nIDD_PREF_TAB_AUTH AFX_DIALOG_LAYOUT\nBEGIN\n    0\nEND\n\nIDD_PREF_TAB_PLAYBACK AFX_DIALOG_LAYOUT\nBEGIN\n    0\nEND\n\n\n#ifdef APSTUDIO_INVOKED\n/////////////////////////////////////////////////////////////////////////////\n//\n// TEXTINCLUDE\n//\n\n1 TEXTINCLUDE \nBEGIN\n    \"resource.h\\0\"\nEND\n\n2 TEXTINCLUDE \nBEGIN\n    \"#define APSTUDIO_HIDDEN_SYMBOLS\\r\\n\"\n    \"#include \"\"windows.h\"\"\\r\\n\"\n    \"#undef APSTUDIO_HIDDEN_SYMBOLS\\r\\n\"\n    \"\\r\\n\"\n    \"#include <atlres.h>\\r\\n\"\n    \"#include <component_defines.h>\\r\\n\"\n    \"\\0\"\nEND\n\n3 TEXTINCLUDE \nBEGIN\n    \"#include \"\"foo_spotify.rc2\"\"\\0\"\nEND\n\n#endif    // APSTUDIO_INVOKED\n\n#endif    // English (United States) resources\n/////////////////////////////////////////////////////////////////////////////\n\n\n\n#ifndef APSTUDIO_INVOKED\n/////////////////////////////////////////////////////////////////////////////\n//\n// Generated from the TEXTINCLUDE 3 resource.\n//\n#include \"foo_spotify.rc2\"\n/////////////////////////////////////////////////////////////////////////////\n#endif    // not APSTUDIO_INVOKED\n\n"
  },
  {
    "path": "foo_spotify/foo_spotify.rc2",
    "content": "//\n// foo_spotify.rc2 - resources Microsoft Visual C++ does not edit directly\n//\n\n#ifdef APSTUDIO_INVOKED\n   #error this file is not editable by Microsoft Visual C++\n#endif  // APSTUDIO_INVOKED\n\n#include <component_defines.h>\n\n#if !defined( AFX_RESOURCE_DLL ) || defined( AFX_TARG_ENU )\nLANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US\n#    pragma code_page( 1252 )\n\n/////////////////////////////////////////////////////////////////////////////\n//\n// Version\n//\n\nVS_VERSION_INFO VERSIONINFO\n FILEVERSION SPTF_VERSION_MAJOR,SPTF_VERSION_MINOR,SPTF_VERSION_PATCH,0\n PRODUCTVERSION SPTF_VERSION_MAJOR,SPTF_VERSION_MINOR,SPTF_VERSION_PATCH,0\n FILEFLAGSMASK 0x3fL\n#ifdef _DEBUG\n#ifdef SPTF_VERSION_PRERELEASE_TEXT\n FILEFLAGS 0x3L\n#else\n FILEFLAGS 0x1L\n#endif\n#else\n#ifdef SPTF_VERSION_PRERELEASE_TEXT\n FILEFLAGS 0x2L\n#else\n FILEFLAGS 0x0L\n#endif\n#endif\n FILEOS 0x40004L\n FILETYPE 0x2L\n FILESUBTYPE 0x0L\nBEGIN\n    BLOCK \"StringFileInfo\"\n    BEGIN\n        BLOCK \"040904b0\"\n        BEGIN\n            VALUE \"FileDescription\", SPTF_NAME \" component for foobar2000\"\n            VALUE \"FileVersion\", SPTF_VERSION\n            VALUE \"InternalName\", SPTF_DLL_NAME\n            VALUE \"LegalCopyright\", \"Copyright (C) 2020 Yuri Shutenko\"\n            VALUE \"OriginalFilename\", SPTF_DLL_NAME\n            VALUE \"ProductName\", SPTF_NAME\n            VALUE \"ProductVersion\", SPTF_VERSION\n        END\n    END\n    BLOCK \"VarFileInfo\"\n    BEGIN\n        VALUE \"Translation\", 0x409, 1200\n    END\nEND\n\n#endif \n"
  },
  {
    "path": "foo_spotify/foo_spotify.vcxproj",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<Project DefaultTargets=\"Build\" ToolsVersion=\"14.0\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\n  <Import Project=\"..\\workspaces\\packages\\Microsoft.SourceLink.GitHub.1.0.0\\build\\Microsoft.SourceLink.GitHub.props\" Condition=\"Exists('..\\workspaces\\packages\\Microsoft.SourceLink.GitHub.1.0.0\\build\\Microsoft.SourceLink.GitHub.props')\" />\n  <Import Project=\"..\\workspaces\\packages\\Microsoft.SourceLink.Common.1.0.0\\build\\Microsoft.SourceLink.Common.props\" Condition=\"Exists('..\\workspaces\\packages\\Microsoft.SourceLink.Common.1.0.0\\build\\Microsoft.SourceLink.Common.props')\" />\n  <Import Project=\"..\\workspaces\\packages\\Microsoft.Build.Tasks.Git.1.0.0\\build\\Microsoft.Build.Tasks.Git.props\" Condition=\"Exists('..\\workspaces\\packages\\Microsoft.Build.Tasks.Git.1.0.0\\build\\Microsoft.Build.Tasks.Git.props')\" />\n  <ItemGroup Label=\"ProjectConfigurations\">\n    <ProjectConfiguration Include=\"Debug|Win32\">\n      <Configuration>Debug</Configuration>\n      <Platform>Win32</Platform>\n    </ProjectConfiguration>\n    <ProjectConfiguration Include=\"Release|Win32\">\n      <Configuration>Release</Configuration>\n      <Platform>Win32</Platform>\n    </ProjectConfiguration>\n  </ItemGroup>\n  <PropertyGroup Label=\"Globals\">\n    <RootNamespace>foo_spotify</RootNamespace>\n    <WindowsTargetPlatformVersion>10.0.18362.0</WindowsTargetPlatformVersion>\n    <ProjectGuid>{FB107A12-DEFC-4782-97FB-EC155B13550C}</ProjectGuid>\n    <VcpkgTriplet>x86-windows-static</VcpkgTriplet>\n  </PropertyGroup>\n  <Import Project=\"$(VCTargetsPath)\\Microsoft.Cpp.Default.props\" />\n  <PropertyGroup Label=\"Configuration\">\n    <ConfigurationType>DynamicLibrary</ConfigurationType>\n    <CharacterSet>Unicode</CharacterSet>\n    <PlatformToolset>v142</PlatformToolset>\n  </PropertyGroup>\n  <PropertyGroup Condition=\"'$(Configuration)'=='Release'\" Label=\"Configuration\">\n    <WholeProgramOptimization>true</WholeProgramOptimization>\n  </PropertyGroup>\n  <Import Project=\"$(VCTargetsPath)\\Microsoft.Cpp.props\" />\n  <ImportGroup Label=\"ExtensionSettings\">\n  </ImportGroup>\n  <ImportGroup Label=\"PropertySheets\">\n    <Import Project=\"$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props\" Condition=\"exists('$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props')\" Label=\"LocalAppDataPlatform\" />\n    <Import Project=\"$(SolutionDir)\\..\\props\\submodules\\submodules.props\" />\n    <Import Project=\"$(SolutionDir)\\..\\props\\submodules\\fb2k_utils.props\" />\n    <Import Project=\"$(QwrFb2kUtilsPropsDir)env\\BuildEnvCommon.props\" />\n    <Import Project=\"$(QwrFb2kUtilsPropsDir)env\\BuildEnvCpp.props\" />\n    <Import Project=\"$(QwrFb2kUtilsPropsDir)env\\StaticRuntime.props\" />\n    <Import Project=\"$(QwrFb2kUtilsPropsDir)submodules\\fmt.props\" />\n    <Import Project=\"$(QwrFb2kUtilsPropsDir)submodules\\foobar2000_sdk.props\" />\n    <Import Project=\"$(QwrFb2kUtilsPropsDir)submodules\\json.props\" />\n    <Import Project=\"$(QwrFb2kUtilsPropsDir)submodules\\range.props\" />\n    <Import Project=\"$(QwrFb2kUtilsPropsDir)submodules\\ring_span.props\" />\n    <Import Project=\"$(QwrFb2kUtilsPropsDir)submodules\\pfc.props\" />\n    <Import Project=\"$(QwrFb2kUtilsPropsDir)submodules\\span.props\" />\n    <Import Project=\"$(QwrFb2kUtilsPropsDir)submodules\\wtl.props\" />\n    <Import Project=\"$(SolutionDir)\\..\\props\\local_dependencies\\libspotify.props\" />\n  </ImportGroup>\n  <PropertyGroup Label=\"UserMacros\" />\n  <PropertyGroup Condition=\"'$(Configuration)'=='Debug'\">\n    <LinkIncremental>true</LinkIncremental>\n  </PropertyGroup>\n  <PropertyGroup>\n    <CAExcludePath>$(IncludePath);$(CAExcludePath)</CAExcludePath>\n  </PropertyGroup>\n  <ItemDefinitionGroup>\n    <ClCompile>\n      <AdditionalIncludeDirectories>$(ProjectDir);$(IncludePath);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\n      <LanguageStandard>stdcpp17</LanguageStandard>\n      <AdditionalOptions>/Zm200 /Zc:__cplusplus /Zc:preprocessor /experimental:newLambdaProcessor %(AdditionalOptions)</AdditionalOptions>\n      <PrecompiledHeader>Use</PrecompiledHeader>\n      <DisableSpecificWarnings>5105</DisableSpecificWarnings>\n      <TreatWarningAsError>true</TreatWarningAsError>\n      <EnforceTypeConversionRules>true</EnforceTypeConversionRules>\n      <RuntimeTypeInfo>false</RuntimeTypeInfo>\n      <ConformanceMode>true</ConformanceMode>\n      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>\n      <AdditionalOptions>-await %(AdditionalOptions)</AdditionalOptions>\n    </ClCompile>\n    <Link>\n      <AdditionalDependencies>credui.lib;%(AdditionalDependencies)</AdditionalDependencies>\n      <SubSystem>Windows</SubSystem>\n      <AdditionalOptions>/SOURCELINK:$(IndependentGeneratedDir)source_link.json %(AdditionalOptions)</AdditionalOptions>\n    </Link>\n  </ItemDefinitionGroup>\n  <ItemDefinitionGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\">\n    <ClCompile>\n      <PreprocessorDefinitions>_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>\n      <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>\n    </ClCompile>\n    <Link>\n      <TargetMachine>MachineX86</TargetMachine>\n      <ImageHasSafeExceptionHandlers>false</ImageHasSafeExceptionHandlers>\n    </Link>\n  </ItemDefinitionGroup>\n  <ItemDefinitionGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\">\n    <ClCompile>\n      <PreprocessorDefinitions>_WINDOWS;_USRDLL;_CRT_SECURE_NO_WARNINGS;_CRT_NON_CONFORMING_SWPRINTFS;%(PreprocessorDefinitions)</PreprocessorDefinitions>\n      <StringPooling>true</StringPooling>\n      <BufferSecurityCheck>false</BufferSecurityCheck>\n      <FloatingPointModel>Fast</FloatingPointModel>\n    </ClCompile>\n    <ResourceCompile>\n      <Culture>0x0409</Culture>\n    </ResourceCompile>\n    <Link>\n      <OptimizeReferences>true</OptimizeReferences>\n      <EnableCOMDATFolding>true</EnableCOMDATFolding>\n      <TargetMachine>MachineX86</TargetMachine>\n    </Link>\n  </ItemDefinitionGroup>\n  <ItemGroup>\n    <ClCompile Include=\"backend\\audio_buffer.cpp\" />\n    <ClCompile Include=\"backend\\libspotify_backend.cpp\" />\n    <ClCompile Include=\"backend\\spotify_instance.cpp\" />\n    <ClCompile Include=\"backend\\spotify_object.cpp\" />\n    <ClCompile Include=\"backend\\webapi_auth.cpp\" />\n    <ClCompile Include=\"backend\\webapi_auth_scopes.cpp\" />\n    <ClCompile Include=\"backend\\webapi_backend.cpp\" />\n    <ClCompile Include=\"backend\\webapi_cache.cpp\" />\n    <ClCompile Include=\"backend\\webapi_objects\\webapi_album.cpp\" />\n    <ClCompile Include=\"backend\\webapi_objects\\webapi_artist.cpp\" />\n    <ClCompile Include=\"backend\\webapi_objects\\webapi_image.cpp\" />\n    <ClCompile Include=\"backend\\webapi_objects\\webapi_paging_object.cpp\" />\n    <ClCompile Include=\"backend\\webapi_objects\\webapi_playlist_track.cpp\" />\n    <ClCompile Include=\"backend\\webapi_objects\\webapi_restriction.cpp\" />\n    <ClCompile Include=\"backend\\webapi_objects\\webapi_track.cpp\" />\n    <ClCompile Include=\"backend\\webapi_objects\\webapi_track_link.cpp\" />\n    <ClCompile Include=\"backend\\webapi_objects\\webapi_user.cpp\" />\n    <ClCompile Include=\"component_paths.cpp\" />\n    <ClCompile Include=\"dllmain.cpp\" />\n    <ClCompile Include=\"fb2k\\acfu_integration.cpp\" />\n    <ClCompile Include=\"fb2k\\advanced_config.cpp\" />\n    <ClCompile Include=\"fb2k\\album_art.cpp\" />\n    <ClCompile Include=\"fb2k\\config.cpp\" />\n    <ClCompile Include=\"fb2k\\filesystem.cpp\" />\n    <ClCompile Include=\"fb2k\\file_info_filler.cpp\" />\n    <ClCompile Include=\"fb2k\\input.cpp\" />\n    <ClCompile Include=\"fb2k\\playback.cpp\" />\n    <ClCompile Include=\"fb2k\\playlist.cpp\" />\n    <ClCompile Include=\"fb2k\\playlist_loader.cpp\" />\n    <ClCompile Include=\"stdafx.cpp\">\n      <PrecompiledHeader>Create</PrecompiledHeader>\n      <PrecompiledHeaderFile>stdafx.h</PrecompiledHeaderFile>\n    </ClCompile>\n    <ClCompile Include=\"ui\\ui_not_auth.cpp\" />\n    <ClCompile Include=\"ui\\ui_pref_tab_auth.cpp\" />\n    <ClCompile Include=\"ui\\ui_pref_tab_manager.cpp\" />\n    <ClCompile Include=\"ui\\ui_pref_tab_playback.cpp\" />\n    <ClCompile Include=\"utils\\abort_manager.cpp\" />\n    <ClCompile Include=\"utils\\cred_prompt.cpp\" />\n    <ClCompile Include=\"utils\\rps_limiter.cpp\" />\n    <ClCompile Include=\"utils\\sleeper.cpp\" />\n  </ItemGroup>\n  <ItemGroup>\n    <ClInclude Include=\"backend\\audio_buffer.h\" />\n    <ClInclude Include=\"backend\\libspotify_key.h\" />\n    <ClInclude Include=\"backend\\libspotify_backend_user.h\" />\n    <ClInclude Include=\"backend\\libspotify_wrapper.h\" />\n    <ClInclude Include=\"backend\\libspotify_backend.h\" />\n    <ClInclude Include=\"backend\\spotify_instance.h\" />\n    <ClInclude Include=\"backend\\spotify_object.h\" />\n    <ClInclude Include=\"backend\\webapi_auth.h\" />\n    <ClInclude Include=\"backend\\webapi_auth_scopes.h\" />\n    <ClInclude Include=\"backend\\webapi_backend.h\" />\n    <ClInclude Include=\"backend\\webapi_objects\\webapi_image.h\" />\n    <ClInclude Include=\"backend\\webapi_objects\\webapi_album.h\" />\n    <ClInclude Include=\"backend\\webapi_objects\\webapi_artist.h\" />\n    <ClInclude Include=\"backend\\webapi_objects\\webapi_media_objects.h\" />\n    <ClInclude Include=\"backend\\webapi_objects\\webapi_paging_object.h\" />\n    <ClInclude Include=\"backend\\webapi_objects\\webapi_playlist_track.h\" />\n    <ClInclude Include=\"backend\\webapi_objects\\webapi_restriction.h\" />\n    <ClInclude Include=\"backend\\webapi_objects\\webapi_track.h\" />\n    <ClInclude Include=\"backend\\webapi_cache.h\" />\n    <ClInclude Include=\"backend\\webapi_objects\\webapi_track_link.h\" />\n    <ClInclude Include=\"backend\\webapi_objects\\webapi_user.h\" />\n    <ClInclude Include=\"component_defines.h\" />\n    <ClInclude Include=\"component_guids.h\" />\n    <ClInclude Include=\"component_paths.h\" />\n    <ClInclude Include=\"component_urls.h\" />\n    <ClInclude Include=\"fb2k\\advanced_config.h\" />\n    <ClInclude Include=\"fb2k\\config.h\" />\n    <ClInclude Include=\"fb2k\\file_info_filler.h\" />\n    <ClInclude Include=\"fb2k\\playback.h\" />\n    <ClInclude Include=\"resource.h\" />\n    <ClInclude Include=\"stdafx.h\" />\n    <ClInclude Include=\"ui\\ui_ipref_tab.h\" />\n    <ClInclude Include=\"ui\\ui_not_auth.h\" />\n    <ClInclude Include=\"ui\\ui_pref_tab_auth.h\" />\n    <ClInclude Include=\"ui\\ui_pref_tab_manager.h\" />\n    <ClInclude Include=\"ui\\ui_pref_tab_playback.h\" />\n    <ClInclude Include=\"utils\\abort_manager.h\" />\n    <ClInclude Include=\"utils\\async_mutex.hpp\" />\n    <ClInclude Include=\"utils\\cred_prompt.h\" />\n    <ClInclude Include=\"utils\\json_macro_fix.h\" />\n    <ClInclude Include=\"utils\\json_std_extenders.h\" />\n    <ClInclude Include=\"utils\\rps_limiter.h\" />\n    <ClInclude Include=\"utils\\secure_vector.h\" />\n    <ClInclude Include=\"utils\\sleeper.h\" />\n  </ItemGroup>\n  <ItemGroup>\n    <ProjectReference Include=\"..\\submodules\\fb2k_utils\\src\\fb2k_utils.vcxproj\">\n      <Project>{ee3bf4f9-2014-4cff-96c8-44cfb85e0571}</Project>\n    </ProjectReference>\n    <ProjectReference Include=\"..\\submodules\\foobar2000\\foobar2000_component_client\\foobar2000_component_client.vcxproj\">\n      <Project>{71ad2674-065b-48f5-b8b0-e1f9d3892081}</Project>\n    </ProjectReference>\n    <ProjectReference Include=\"..\\submodules\\foobar2000\\SDK\\foobar2000_SDK.vcxproj\">\n      <Project>{e8091321-d79d-4575-86ef-064ea1a4a20d}</Project>\n    </ProjectReference>\n    <ProjectReference Include=\"..\\submodules\\pfc\\pfc.vcxproj\">\n      <Project>{ebfffb4e-261d-44d3-b89c-957b31a0bf9c}</Project>\n    </ProjectReference>\n  </ItemGroup>\n  <ItemGroup>\n    <ResourceCompile Include=\"foo_spotify.rc\" />\n  </ItemGroup>\n  <ItemGroup>\n    <None Include=\"foo_spotify.rc2\" />\n  </ItemGroup>\n  <Import Project=\"$(VCTargetsPath)\\Microsoft.Cpp.targets\" />\n  <ImportGroup Label=\"ExtensionTargets\">\n    <Import Project=\"..\\workspaces\\packages\\Microsoft.Build.Tasks.Git.1.0.0\\build\\Microsoft.Build.Tasks.Git.targets\" Condition=\"Exists('..\\workspaces\\packages\\Microsoft.Build.Tasks.Git.1.0.0\\build\\Microsoft.Build.Tasks.Git.targets')\" />\n    <Import Project=\"..\\workspaces\\packages\\Microsoft.SourceLink.Common.1.0.0\\build\\Microsoft.SourceLink.Common.targets\" Condition=\"Exists('..\\workspaces\\packages\\Microsoft.SourceLink.Common.1.0.0\\build\\Microsoft.SourceLink.Common.targets')\" />\n    <Import Project=\"..\\workspaces\\packages\\Microsoft.SourceLink.GitHub.1.0.0\\build\\Microsoft.SourceLink.GitHub.targets\" Condition=\"Exists('..\\workspaces\\packages\\Microsoft.SourceLink.GitHub.1.0.0\\build\\Microsoft.SourceLink.GitHub.targets')\" />\n  </ImportGroup>\n  <Target Name=\"EnsureNuGetPackageBuildImports\" BeforeTargets=\"PrepareForBuild\">\n    <PropertyGroup>\n      <ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them.  For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>\n    </PropertyGroup>\n    <Error Condition=\"!Exists('..\\workspaces\\packages\\Microsoft.Build.Tasks.Git.1.0.0\\build\\Microsoft.Build.Tasks.Git.props')\" Text=\"$([System.String]::Format('$(ErrorText)', '..\\workspaces\\packages\\Microsoft.Build.Tasks.Git.1.0.0\\build\\Microsoft.Build.Tasks.Git.props'))\" />\n    <Error Condition=\"!Exists('..\\workspaces\\packages\\Microsoft.Build.Tasks.Git.1.0.0\\build\\Microsoft.Build.Tasks.Git.targets')\" Text=\"$([System.String]::Format('$(ErrorText)', '..\\workspaces\\packages\\Microsoft.Build.Tasks.Git.1.0.0\\build\\Microsoft.Build.Tasks.Git.targets'))\" />\n    <Error Condition=\"!Exists('..\\workspaces\\packages\\Microsoft.SourceLink.Common.1.0.0\\build\\Microsoft.SourceLink.Common.props')\" Text=\"$([System.String]::Format('$(ErrorText)', '..\\workspaces\\packages\\Microsoft.SourceLink.Common.1.0.0\\build\\Microsoft.SourceLink.Common.props'))\" />\n    <Error Condition=\"!Exists('..\\workspaces\\packages\\Microsoft.SourceLink.Common.1.0.0\\build\\Microsoft.SourceLink.Common.targets')\" Text=\"$([System.String]::Format('$(ErrorText)', '..\\workspaces\\packages\\Microsoft.SourceLink.Common.1.0.0\\build\\Microsoft.SourceLink.Common.targets'))\" />\n    <Error Condition=\"!Exists('..\\workspaces\\packages\\Microsoft.SourceLink.GitHub.1.0.0\\build\\Microsoft.SourceLink.GitHub.props')\" Text=\"$([System.String]::Format('$(ErrorText)', '..\\workspaces\\packages\\Microsoft.SourceLink.GitHub.1.0.0\\build\\Microsoft.SourceLink.GitHub.props'))\" />\n    <Error Condition=\"!Exists('..\\workspaces\\packages\\Microsoft.SourceLink.GitHub.1.0.0\\build\\Microsoft.SourceLink.GitHub.targets')\" Text=\"$([System.String]::Format('$(ErrorText)', '..\\workspaces\\packages\\Microsoft.SourceLink.GitHub.1.0.0\\build\\Microsoft.SourceLink.GitHub.targets'))\" />\n  </Target>\n</Project>"
  },
  {
    "path": "foo_spotify/foo_spotify.vcxproj.filters",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<Project ToolsVersion=\"4.0\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\n  <ItemGroup>\n    <ClCompile Include=\"stdafx.cpp\" />\n    <ClCompile Include=\"dllmain.cpp\" />\n    <ClCompile Include=\"fb2k\\input.cpp\">\n      <Filter>fb2k</Filter>\n    </ClCompile>\n    <ClCompile Include=\"backend\\libspotify_backend.cpp\">\n      <Filter>backend</Filter>\n    </ClCompile>\n    <ClCompile Include=\"utils\\cred_prompt.cpp\">\n      <Filter>utils</Filter>\n    </ClCompile>\n    <ClCompile Include=\"fb2k\\album_art.cpp\">\n      <Filter>fb2k</Filter>\n    </ClCompile>\n    <ClCompile Include=\"fb2k\\playback.cpp\">\n      <Filter>fb2k</Filter>\n    </ClCompile>\n    <ClCompile Include=\"backend\\webapi_auth.cpp\">\n      <Filter>backend</Filter>\n    </ClCompile>\n    <ClCompile Include=\"component_paths.cpp\" />\n    <ClCompile Include=\"backend\\webapi_backend.cpp\">\n      <Filter>backend</Filter>\n    </ClCompile>\n    <ClCompile Include=\"fb2k\\playlist_loader.cpp\">\n      <Filter>fb2k</Filter>\n    </ClCompile>\n    <ClCompile Include=\"backend\\webapi_objects\\webapi_image.cpp\">\n      <Filter>backend\\webapi_objects</Filter>\n    </ClCompile>\n    <ClCompile Include=\"backend\\webapi_objects\\webapi_track.cpp\">\n      <Filter>backend\\webapi_objects</Filter>\n    </ClCompile>\n    <ClCompile Include=\"backend\\webapi_objects\\webapi_album.cpp\">\n      <Filter>backend\\webapi_objects</Filter>\n    </ClCompile>\n    <ClCompile Include=\"backend\\webapi_objects\\webapi_artist.cpp\">\n      <Filter>backend\\webapi_objects</Filter>\n    </ClCompile>\n    <ClCompile Include=\"fb2k\\advanced_config.cpp\">\n      <Filter>fb2k</Filter>\n    </ClCompile>\n    <ClCompile Include=\"backend\\webapi_cache.cpp\">\n      <Filter>backend</Filter>\n    </ClCompile>\n    <ClCompile Include=\"backend\\spotify_object.cpp\">\n      <Filter>backend</Filter>\n    </ClCompile>\n    <ClCompile Include=\"fb2k\\file_info_filler.cpp\">\n      <Filter>fb2k</Filter>\n    </ClCompile>\n    <ClCompile Include=\"backend\\webapi_objects\\webapi_playlist_track.cpp\">\n      <Filter>backend\\webapi_objects</Filter>\n    </ClCompile>\n    <ClCompile Include=\"utils\\abort_manager.cpp\">\n      <Filter>utils</Filter>\n    </ClCompile>\n    <ClCompile Include=\"backend\\webapi_objects\\webapi_user.cpp\">\n      <Filter>backend\\webapi_objects</Filter>\n    </ClCompile>\n    <ClCompile Include=\"backend\\spotify_instance.cpp\">\n      <Filter>backend</Filter>\n    </ClCompile>\n    <ClCompile Include=\"ui\\ui_not_auth.cpp\">\n      <Filter>ui</Filter>\n    </ClCompile>\n    <ClCompile Include=\"fb2k\\acfu_integration.cpp\">\n      <Filter>fb2k</Filter>\n    </ClCompile>\n    <ClCompile Include=\"fb2k\\config.cpp\">\n      <Filter>fb2k</Filter>\n    </ClCompile>\n    <ClCompile Include=\"backend\\audio_buffer.cpp\">\n      <Filter>backend</Filter>\n    </ClCompile>\n    <ClCompile Include=\"fb2k\\filesystem.cpp\">\n      <Filter>fb2k</Filter>\n    </ClCompile>\n    <ClCompile Include=\"backend\\webapi_auth_scopes.cpp\">\n      <Filter>backend</Filter>\n    </ClCompile>\n    <ClCompile Include=\"backend\\webapi_objects\\webapi_restriction.cpp\">\n      <Filter>backend\\webapi_objects</Filter>\n    </ClCompile>\n    <ClCompile Include=\"backend\\webapi_objects\\webapi_track_link.cpp\">\n      <Filter>backend\\webapi_objects</Filter>\n    </ClCompile>\n    <ClCompile Include=\"utils\\sleeper.cpp\">\n      <Filter>utils</Filter>\n    </ClCompile>\n    <ClCompile Include=\"ui\\ui_pref_tab_manager.cpp\">\n      <Filter>ui</Filter>\n    </ClCompile>\n    <ClCompile Include=\"ui\\ui_pref_tab_auth.cpp\">\n      <Filter>ui</Filter>\n    </ClCompile>\n    <ClCompile Include=\"ui\\ui_pref_tab_playback.cpp\">\n      <Filter>ui</Filter>\n    </ClCompile>\n    <ClCompile Include=\"utils\\rps_limiter.cpp\">\n      <Filter>utils</Filter>\n    </ClCompile>\n    <ClCompile Include=\"fb2k\\playlist.cpp\">\n      <Filter>fb2k</Filter>\n    </ClCompile>\n    <ClCompile Include=\"backend\\webapi_objects\\webapi_paging_object.cpp\">\n      <Filter>backend\\webapi_objects</Filter>\n    </ClCompile>\n  </ItemGroup>\n  <ItemGroup>\n    <ClInclude Include=\"component_defines.h\" />\n    <ClInclude Include=\"component_guids.h\" />\n    <ClInclude Include=\"stdafx.h\" />\n    <ClInclude Include=\"utils\\secure_vector.h\">\n      <Filter>utils</Filter>\n    </ClInclude>\n    <ClInclude Include=\"backend\\audio_buffer.h\">\n      <Filter>backend</Filter>\n    </ClInclude>\n    <ClInclude Include=\"backend\\libspotify_wrapper.h\">\n      <Filter>backend</Filter>\n    </ClInclude>\n    <ClInclude Include=\"backend\\libspotify_backend.h\">\n      <Filter>backend</Filter>\n    </ClInclude>\n    <ClInclude Include=\"utils\\cred_prompt.h\">\n      <Filter>utils</Filter>\n    </ClInclude>\n    <ClInclude Include=\"backend\\libspotify_backend_user.h\">\n      <Filter>backend</Filter>\n    </ClInclude>\n    <ClInclude Include=\"backend\\libspotify_key.h\">\n      <Filter>backend</Filter>\n    </ClInclude>\n    <ClInclude Include=\"backend\\webapi_auth.h\">\n      <Filter>backend</Filter>\n    </ClInclude>\n    <ClInclude Include=\"utils\\async_mutex.hpp\">\n      <Filter>utils</Filter>\n    </ClInclude>\n    <ClInclude Include=\"component_paths.h\" />\n    <ClInclude Include=\"component_urls.h\" />\n    <ClInclude Include=\"backend\\webapi_backend.h\">\n      <Filter>backend</Filter>\n    </ClInclude>\n    <ClInclude Include=\"backend\\spotify_object.h\">\n      <Filter>backend</Filter>\n    </ClInclude>\n    <ClInclude Include=\"backend\\webapi_objects\\webapi_track.h\">\n      <Filter>backend\\webapi_objects</Filter>\n    </ClInclude>\n    <ClInclude Include=\"backend\\webapi_objects\\webapi_album.h\">\n      <Filter>backend\\webapi_objects</Filter>\n    </ClInclude>\n    <ClInclude Include=\"backend\\webapi_objects\\webapi_artist.h\">\n      <Filter>backend\\webapi_objects</Filter>\n    </ClInclude>\n    <ClInclude Include=\"backend\\webapi_objects\\webapi_image.h\">\n      <Filter>backend\\webapi_objects</Filter>\n    </ClInclude>\n    <ClInclude Include=\"utils\\json_std_extenders.h\">\n      <Filter>utils</Filter>\n    </ClInclude>\n    <ClInclude Include=\"utils\\json_macro_fix.h\">\n      <Filter>utils</Filter>\n    </ClInclude>\n    <ClInclude Include=\"fb2k\\advanced_config.h\">\n      <Filter>fb2k</Filter>\n    </ClInclude>\n    <ClInclude Include=\"backend\\webapi_cache.h\">\n      <Filter>backend</Filter>\n    </ClInclude>\n    <ClInclude Include=\"fb2k\\file_info_filler.h\">\n      <Filter>fb2k</Filter>\n    </ClInclude>\n    <ClInclude Include=\"utils\\abort_manager.h\">\n      <Filter>utils</Filter>\n    </ClInclude>\n    <ClInclude Include=\"resource.h\">\n      <Filter>resources</Filter>\n    </ClInclude>\n    <ClInclude Include=\"backend\\webapi_objects\\webapi_playlist_track.h\">\n      <Filter>backend\\webapi_objects</Filter>\n    </ClInclude>\n    <ClInclude Include=\"backend\\webapi_objects\\webapi_user.h\">\n      <Filter>backend\\webapi_objects</Filter>\n    </ClInclude>\n    <ClInclude Include=\"backend\\spotify_instance.h\">\n      <Filter>backend</Filter>\n    </ClInclude>\n    <ClInclude Include=\"fb2k\\playback.h\">\n      <Filter>fb2k</Filter>\n    </ClInclude>\n    <ClInclude Include=\"ui\\ui_not_auth.h\">\n      <Filter>ui</Filter>\n    </ClInclude>\n    <ClInclude Include=\"fb2k\\config.h\">\n      <Filter>fb2k</Filter>\n    </ClInclude>\n    <ClInclude Include=\"backend\\webapi_auth_scopes.h\">\n      <Filter>backend</Filter>\n    </ClInclude>\n    <ClInclude Include=\"backend\\webapi_objects\\webapi_restriction.h\">\n      <Filter>backend\\webapi_objects</Filter>\n    </ClInclude>\n    <ClInclude Include=\"backend\\webapi_objects\\webapi_media_objects.h\">\n      <Filter>backend\\webapi_objects</Filter>\n    </ClInclude>\n    <ClInclude Include=\"backend\\webapi_objects\\webapi_track_link.h\">\n      <Filter>backend\\webapi_objects</Filter>\n    </ClInclude>\n    <ClInclude Include=\"utils\\sleeper.h\">\n      <Filter>utils</Filter>\n    </ClInclude>\n    <ClInclude Include=\"ui\\ui_pref_tab_manager.h\">\n      <Filter>ui</Filter>\n    </ClInclude>\n    <ClInclude Include=\"ui\\ui_pref_tab_auth.h\">\n      <Filter>ui</Filter>\n    </ClInclude>\n    <ClInclude Include=\"ui\\ui_ipref_tab.h\">\n      <Filter>ui</Filter>\n    </ClInclude>\n    <ClInclude Include=\"ui\\ui_pref_tab_playback.h\">\n      <Filter>ui</Filter>\n    </ClInclude>\n    <ClInclude Include=\"utils\\rps_limiter.h\">\n      <Filter>utils</Filter>\n    </ClInclude>\n    <ClInclude Include=\"backend\\webapi_objects\\webapi_paging_object.h\">\n      <Filter>backend\\webapi_objects</Filter>\n    </ClInclude>\n  </ItemGroup>\n  <ItemGroup>\n    <Filter Include=\"utils\">\n      <UniqueIdentifier>{39367257-b161-4f23-b132-bcf2bc7a7b1e}</UniqueIdentifier>\n    </Filter>\n    <Filter Include=\"backend\">\n      <UniqueIdentifier>{b367b073-47b1-4060-9fb1-165c7d6558c8}</UniqueIdentifier>\n    </Filter>\n    <Filter Include=\"fb2k\">\n      <UniqueIdentifier>{a36e2bb9-5034-4b8e-9275-aac759906267}</UniqueIdentifier>\n    </Filter>\n    <Filter Include=\"backend\\webapi_objects\">\n      <UniqueIdentifier>{9f4d57e0-bdd7-495d-a54d-0c753b8c738e}</UniqueIdentifier>\n    </Filter>\n    <Filter Include=\"ui\">\n      <UniqueIdentifier>{20a66e7a-1826-4915-8807-e86a5c3df4f8}</UniqueIdentifier>\n    </Filter>\n    <Filter Include=\"resources\">\n      <UniqueIdentifier>{4cc30a63-061e-4a1c-a2f1-8ecc63d6f357}</UniqueIdentifier>\n    </Filter>\n  </ItemGroup>\n  <ItemGroup>\n    <ResourceCompile Include=\"foo_spotify.rc\">\n      <Filter>resources</Filter>\n    </ResourceCompile>\n  </ItemGroup>\n  <ItemGroup>\n    <None Include=\"foo_spotify.rc2\">\n      <Filter>resources</Filter>\n    </None>\n  </ItemGroup>\n</Project>"
  },
  {
    "path": "foo_spotify/packages.config",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<packages>\n  <package id=\"Microsoft.Build.Tasks.Git\" version=\"1.0.0\" targetFramework=\"native\" developmentDependency=\"true\" />\n  <package id=\"Microsoft.SourceLink.Common\" version=\"1.0.0\" targetFramework=\"native\" developmentDependency=\"true\" />\n  <package id=\"Microsoft.SourceLink.GitHub\" version=\"1.0.0\" targetFramework=\"native\" developmentDependency=\"true\" />\n</packages>"
  },
  {
    "path": "foo_spotify/resource.h",
    "content": "//{{NO_DEPENDENCIES}}\n// Microsoft Visual C++ generated include file.\n// Used by foo_spotify.rc\n//\n#define VS_VERSION_INFO              1\n#define IDD_PREF_TAB_HOST            101\n#define IDD_NOT_AUTH                 102\n#define IDD_PREF_TAB_AUTH            103\n#define IDD_PREF_TAB_PLAYBACK        104\n#define IDC_BTN_LOGIN_LIBSPOTIFY     1003\n#define IDC_BTN_LOGIN_WEBAPI         1004\n#define IDC_STATIC_LIBSPOTIFY_STATUS 1005\n#define IDC_STATIC_WEBAPI_STATUS     1006\n#define IDC_BTN_OPEN_PREF            1007\n#define IDC_STATIC_NOT_AUTH          1008\n#define IDC_COMBO_BITRATE            1009\n#define IDC_CHECK_NORMALIZE          1010\n#define IDC_CHECK_PRIVATE            1011\n#define IDC_TAB_HOST                 1012\n#define IDC_SLIDER_CACHE_MB          1013\n#define IDC_SLIDER_CACHE_PERCENT     1014\n#define IDC_EDIT_CACHE_MB            1015\n#define IDC_EDIT_CACHE_PERCENT       1016\n\n// Next default values for new objects\n//\n#ifdef APSTUDIO_INVOKED\n#    ifndef APSTUDIO_READONLY_SYMBOLS\n#        define _APS_NEXT_RESOURCE_VALUE 105\n#        define _APS_NEXT_COMMAND_VALUE  40001\n#        define _APS_NEXT_CONTROL_VALUE  1017\n#        define _APS_NEXT_SYMED_VALUE    101\n#    endif\n#endif\n"
  },
  {
    "path": "foo_spotify/stdafx.cpp",
    "content": "#include <stdafx.h>\n"
  },
  {
    "path": "foo_spotify/stdafx.h",
    "content": "#pragma once\n\n// clang-format off\n// !!! Include order is important here (esp. for Win headers) !!!\n\n// Support only Windows 7 and newer\n#define _WIN32_WINNT _WIN32_WINNT_WIN7\n#define WINVER _WIN32_WINNT_WIN7\n\n// Fix std min max conflicts\n#define NOMINMAX\n#include <WinSock2.h>\n#include <Windows.h>\n\n// ATL/WTL\n/// atlstr.h (includes atlbase.h) must be included first for CString to LPTSTR conversion to work.\n#include <atlstr.h> \n#include <atlapp.h>\n#include <atlcom.h>\n#include <atlcrack.h>\n#include <atlctrls.h>\n#include <atlddx.h>\n#include <atldlgs.h>\n#include <atlfind.h>\n#include <atlframe.h>\n#include <atltheme.h>\n#include <atltypes.h>\n#include <atlwin.h>\n\n// foobar2000 SDK\n#pragma warning( push, 0 )\n#   include <foobar2000/SDK/foobar2000.h>\n#pragma warning( pop ) \n\n// fmt\n#define FMT_HEADER_ONLY\n#include <fmt/format.h>\n\n// nlohmann json\n#include <nlohmann/json.hpp>\n\n// range v3\n#include <range/v3/all.hpp>\n\n#if not __cpp_char8_t\n// Dummy type\n#include <string>\n\nusing char8_t = char;\nnamespace std // NOLINT(cert-dcl58-cpp)\n{\nusing u8string = basic_string<char8_t, char_traits<char8_t>, allocator<char8_t>>;\nusing u8string_view = basic_string_view<char8_t>;\n}\n#endif\n\n// Additional PFC wrappers\n#include <qwr/pfc_helpers_cnt.h>\n#include <qwr/pfc_helpers_stream.h>\n\n#include <qwr/unicode.h>\n#include <qwr/qwr_exception.h>\n\n#include <utils/json_macro_fix.h>\n\n#include <component_defines.h>\n#include <component_guids.h>\n#include <component_paths.h>\n\n// clang-format on\n"
  },
  {
    "path": "foo_spotify/ui/ui_ipref_tab.h",
    "content": "#pragma once\n\nnamespace sptf::ui\n{\n\nclass IPrefTab\n{\npublic:\n    virtual ~IPrefTab() = default;\n\n    virtual HWND CreateTab( HWND hParent ) = 0;\n    virtual CDialogImplBase& Dialog() = 0;\n    virtual const wchar_t* Name() const = 0;\n\n    // preferences_page_instance\n\n    //! @returns a combination of preferences_state constants.\n    virtual uint32_t get_state() = 0;\n    //! @returns the window handle.\n    //! Applies preferences changes.\n    virtual void apply() = 0;\n    //! Resets this page's content to the default values. Does not apply any changes - lets user preview the changes before hitting \"apply\".\n    virtual void reset() = 0;\n};\n\n} // namespace sptf::ui\n"
  },
  {
    "path": "foo_spotify/ui/ui_not_auth.cpp",
    "content": "#include <stdafx.h>\n\n#include \"ui_not_auth.h\"\n\n#include <qwr/hook_handler.h>\n\nnamespace sptf::ui\n{\n\nNotAuth::NotAuth( std::function<void()> onDestroyCallback )\n    : onDestroyCallback_( onDestroyCallback )\n{\n}\n\nBOOL NotAuth::OnInitDialog( HWND hwndFocus, LPARAM lParam )\n{\n    hookId_ = qwr::HookHandler::GetInstance().RegisterHook(\n        [hParent = m_hWnd]( int code, WPARAM wParam, LPARAM lParam ) {\n            GetMsgProc( code, wParam, lParam, hParent );\n        } );\n\n    SetWindowText( TEXT( SPTF_NAME ) );\n\n    CStatic text( GetDlgItem( IDC_STATIC_NOT_AUTH ) );\n    text.SetWindowText( fmt::format(\n                            L\"{} ({}) requires Spotify Premium account.\\n\"\n                            L\"Open the corresponding foobar2000 Preferences page to authorize.\",\n                            TEXT( SPTF_NAME ),\n                            TEXT( SPTF_UNDERSCORE_NAME ) )\n                            .c_str() );\n\n    return TRUE; // set focus to default control\n}\n\nvoid NotAuth::OnDestroy()\n{\n    if ( hookId_ )\n    {\n        qwr::HookHandler::GetInstance().UnregisterHook( hookId_ );\n        hookId_ = 0;\n    }\n}\n\nvoid NotAuth::OnCloseCmd( UINT uNotifyCode, int nID, CWindow wndCtl )\n{\n    DestroyWindow();\n}\n\nvoid NotAuth::OnOpenPrefClick( UINT uNotifyCode, int nID, CWindow wndCtl )\n{\n    ::fb2k::inMainThread( [] { ui_control::get()->show_preferences( sptf::guid::preferences ); } );\n    DestroyWindow();\n}\n\nvoid NotAuth::OnFinalMessage( _In_ HWND /*hWnd*/ )\n{\n    onDestroyCallback_();\n    delete this;\n}\n\nvoid NotAuth::GetMsgProc( int, WPARAM, LPARAM lParam, HWND hParent )\n{\n    if ( auto pMsg = reinterpret_cast<LPMSG>( lParam );\n         pMsg->message >= WM_KEYFIRST && pMsg->message <= WM_KEYLAST )\n    { // Only react to keypress events\n        HWND hWndFocus = ::GetFocus();\n        if ( hWndFocus != nullptr && ( ( hParent == hWndFocus ) || ::IsChild( hParent, hWndFocus ) ) )\n        {\n            if ( ::IsDialogMessage( hParent, pMsg ) )\n            {\n                pMsg->message = WM_NULL;\n            }\n        }\n    }\n}\n\nNotAuthHandler& NotAuthHandler::Get()\n{\n    static NotAuthHandler nah;\n    return nah;\n}\n\nvoid NotAuthHandler::ShowDialog()\n{\n    assert( core_api::is_main_thread() );\n    if ( !pNotAuth_ )\n    {\n        pNotAuth_ = new ui::NotAuth( [&] {\n            assert( core_api::is_main_thread() );\n            pNotAuth_ = nullptr;\n        } );\n        if ( !pNotAuth_->Create( core_api::get_main_window() ) )\n        {\n            delete pNotAuth_;\n            pNotAuth_ = nullptr;\n            return;\n        }\n\n        pNotAuth_->SetActiveWindow();\n        pNotAuth_->CenterWindow( core_api::get_main_window() );\n        pNotAuth_->ShowWindow( SW_SHOW );\n    }\n    else\n    {\n        pNotAuth_->SetActiveWindow();\n        pNotAuth_->ShowWindow( SW_SHOW );\n    }\n}\n\nvoid NotAuthHandler::CloseDialog()\n{\n    assert( core_api::is_main_thread() );\n    if ( pNotAuth_ )\n    {\n        pNotAuth_->DestroyWindow();\n    }\n}\n\n} // namespace sptf::ui"
  },
  {
    "path": "foo_spotify/ui/ui_not_auth.h",
    "content": "#pragma once\n\n#include <resource.h>\n\n#include <mutex>\n\nnamespace sptf::ui\n{\n\nclass NotAuth\n    : public CDialogImpl<NotAuth>\n{\npublic:\n    enum\n    {\n        IDD = IDD_NOT_AUTH\n    };\n\n    NotAuth( std::function<void()> onDestroyCallback );\n    ~NotAuth() = default;\n\nprotected:\n    BEGIN_MSG_MAP( NotAuth )\n        MSG_WM_INITDIALOG( OnInitDialog )\n        MSG_WM_DESTROY( OnDestroy )\n        COMMAND_RANGE_HANDLER_EX( IDOK, IDCANCEL, OnCloseCmd )\n        COMMAND_HANDLER_EX( IDC_BTN_OPEN_PREF, BN_CLICKED, OnOpenPrefClick )\n    END_MSG_MAP()\n\nprivate:\n    BOOL OnInitDialog( HWND hwndFocus, LPARAM lParam );\n    void OnDestroy();\n\n    void OnCloseCmd( UINT uNotifyCode, int nID, CWindow wndCtl );\n    void OnOpenPrefClick( UINT uNotifyCode, int nID, CWindow wndCtl );\n\n    void OnFinalMessage( _In_ HWND hWnd ) override;\n\n    static void GetMsgProc( int code, WPARAM wParam, LPARAM lParam, HWND hParent );\n\nprivate:\n    uint32_t hookId_ = 0;\n    std::function<void()> onDestroyCallback_;\n};\n\nclass NotAuthHandler\n{\npublic:\n    ~NotAuthHandler() = default;\n    static NotAuthHandler& Get();\n\n    void ShowDialog();\n    void CloseDialog();\n\nprivate:\n    NotAuthHandler() = default;\n\nprivate:\n    std::mutex authMutex_;\n    sptf::ui::NotAuth* pNotAuth_ = nullptr;\n};\n\n} // namespace sptf::ui\n"
  },
  {
    "path": "foo_spotify/ui/ui_pref_tab_auth.cpp",
    "content": "#include <stdafx.h>\n\n#include \"ui_pref_tab_auth.h\"\n\n#include <backend/libspotify_backend.h>\n#include <backend/spotify_instance.h>\n#include <backend/webapi_auth.h>\n#include <backend/webapi_auth_scopes.h>\n#include <backend/webapi_backend.h>\n#include <backend/webapi_objects/webapi_user.h>\n#include <fb2k/config.h>\n#include <ui/ui_pref_tab_manager.h>\n\n#include <component_urls.h>\n\n#include <qwr/abort_callback.h>\n#include <qwr/error_popup.h>\n#include <qwr/string_helpers.h>\n\nnamespace sptf::ui\n{\n\nPreferenceTabAuth::PreferenceTabAuth( PreferenceTabManager* pParent )\n    : pParent_( pParent )\n    , ddxOptions_( {} )\n{\n}\n\nPreferenceTabAuth::~PreferenceTabAuth()\n{\n    for ( auto& ddxOpt: ddxOptions_ )\n    {\n        ddxOpt->Option().Revert();\n    }\n}\n\nHWND PreferenceTabAuth::CreateTab( HWND hParent )\n{\n    return Create( hParent );\n}\n\nCDialogImplBase& PreferenceTabAuth::Dialog()\n{\n    return *this;\n}\n\nconst wchar_t* PreferenceTabAuth::Name() const\n{\n    return L\"Authorization\";\n}\n\nt_uint32 PreferenceTabAuth::get_state()\n{\n    const bool hasChanged =\n        ddxOptions_.cend() != std::find_if( ddxOptions_.cbegin(), ddxOptions_.cend(), []( const auto& ddxOpt ) {\n            return ddxOpt->Option().HasChanged();\n        } );\n\n    return ( preferences_state::resettable | ( hasChanged ? preferences_state::changed : 0 ) );\n}\n\nvoid PreferenceTabAuth::apply()\n{\n    for ( auto& ddxOpt: ddxOptions_ )\n    {\n        ddxOpt->Option().Apply();\n    }\n\n    pParent_->OnDataChanged();\n}\n\nvoid PreferenceTabAuth::reset()\n{\n    for ( auto& ddxOpt: ddxOptions_ )\n    {\n        ddxOpt->Option().ResetToDefault();\n    }\n    UpdateUiFromCfg();\n\n    pParent_->OnDataChanged();\n}\n\nBOOL PreferenceTabAuth::OnInitDialog( HWND hwndFocus, LPARAM lParam )\n{\n    btnLibSpotify_ = GetDlgItem( IDC_BTN_LOGIN_LIBSPOTIFY );\n    btnWebApi_ = GetDlgItem( IDC_BTN_LOGIN_WEBAPI );\n\n    textLibSpotify_ = GetDlgItem( IDC_STATIC_LIBSPOTIFY_STATUS );\n    textWebApi_ = GetDlgItem( IDC_STATIC_WEBAPI_STATUS );\n\n    for ( auto& ddxOpt: ddxOptions_ )\n    {\n        ddxOpt->Ddx().SetHwnd( m_hWnd );\n    }\n    UpdateUiFromCfg();\n\n    pStatusThread_ = std::make_unique<std::thread>( [this] {\n        const auto lsStatus = [] {\n            qwr::TimedAbortCallback tac( fmt::format( \"{}: {}\", SPTF_UNDERSCORE_NAME, \"LibSpotify relogin\" ) );\n            return SpotifyInstance::Get().GetLibSpotify_Backend().Relogin( tac );\n        }();\n        const auto waStatus = [&] {\n            auto& auth = SpotifyInstance::Get().GetWebApi_Backend().GetAuthorizer();\n            if ( !auth.HasRefreshToken() )\n            {\n                return false;\n            }\n            try\n            {\n                qwr::TimedAbortCallback tac( fmt::format( \"{}: {}\", SPTF_UNDERSCORE_NAME, \"WebApi relogin\" ) );\n                auth.UpdateRefreshToken( tac );\n                return true;\n            }\n            catch ( const std::exception& )\n            {\n                return false;\n            }\n        }();\n\n        ::PostMessage( m_hWnd, kOnStatusUpdateFinish, WPARAM( lsStatus ), LPARAM( waStatus ) );\n    } );\n\n    UpdateLibSpotifyUi();\n    UpdateWebApiUi();\n\n    return TRUE; // set focus to default control\n}\n\nvoid PreferenceTabAuth::OnDestroy()\n{\n    auto& auth = SpotifyInstance::Get().GetWebApi_Backend().GetAuthorizer();\n    if ( webApiStatus_ == LoginStatus::logged_in )\n    {\n        auth.AuthenticateClean_Cleanup();\n    }\n    else\n    {\n        auth.CancelAuth();\n    }\n\n    if ( pStatusThread_ )\n    {\n        if ( pStatusThread_->joinable() )\n        {\n            pStatusThread_->join();\n        }\n        pStatusThread_.reset();\n    }\n}\n\nHBRUSH PreferenceTabAuth::OnCtlColorStatic( CDCHandle dc, CStatic wndStatic )\n{\n    const auto id = wndStatic.GetDlgCtrlID();\n    if ( id == IDC_STATIC_LIBSPOTIFY_STATUS\n         || id == IDC_STATIC_WEBAPI_STATUS )\n    {\n        const auto getColour = []( auto loginStatus ) {\n            switch ( loginStatus )\n            {\n            case LoginStatus::logged_out:\n            {\n                return RGB( 0x8B, 0x00, 0x00 );\n            }\n            case LoginStatus::logged_in:\n            {\n                return RGB( 0x2F, 0x4F, 0x4f );\n            }\n            default:\n                return RGB( 0xFF, 0x7F, 0x50 );\n            }\n        };\n\n        ::SetTextColor( dc, getColour( id == IDC_STATIC_LIBSPOTIFY_STATUS ? libSpotifyStatus_ : webApiStatus_ ) );\n        ::SetBkColor( dc, GetSysColor( COLOR_WINDOW ) );\n        return (HBRUSH)GetStockObject( HOLLOW_BRUSH );\n    }\n\n    SetMsgHandled( FALSE );\n\n    return 0;\n}\n\nvoid PreferenceTabAuth::OnDdxChange( UINT uNotifyCode, int nID, CWindow wndCtl )\n{\n    auto it = std::find_if( ddxOptions_.begin(), ddxOptions_.end(), [nID]( auto& val ) {\n        return val->Ddx().IsMatchingId( nID );\n    } );\n\n    if ( ddxOptions_.end() != it )\n    {\n        ( *it )->Ddx().ReadFromUi();\n        pParent_->OnDataChanged();\n    }\n}\n\nvoid PreferenceTabAuth::OnLibSpotifyLoginClick( UINT uNotifyCode, int nID, CWindow wndCtl )\n{\n    (void)uNotifyCode;\n    (void)nID;\n    (void)wndCtl;\n\n    auto& lsBackend = SpotifyInstance::Get().GetLibSpotify_Backend();\n    if ( libSpotifyStatus_ == LoginStatus::logged_out )\n    {\n        libSpotifyStatus_ = ( lsBackend.LoginWithUI( m_hWnd ) ? LoginStatus::logged_in : LoginStatus::logged_out );\n    }\n    else\n    {\n        qwr::TimedAbortCallback tac( fmt::format( \"{}: {}\", SPTF_UNDERSCORE_NAME, \"LibSpotify logout\" ) );\n        lsBackend.LogoutAndForget( tac );\n        libSpotifyStatus_ = LoginStatus::logged_out;\n    }\n\n    UpdateLibSpotifyUi();\n}\n\nvoid PreferenceTabAuth::OnWebApiLoginClick( UINT uNotifyCode, int nID, CWindow wndCtl )\n{\n    (void)uNotifyCode;\n    (void)nID;\n    (void)wndCtl;\n\n    auto& auth = SpotifyInstance::Get().GetWebApi_Backend().GetAuthorizer();\n    if ( webApiStatus_ == LoginStatus::logged_out )\n    {\n        // this operation is async\n        webApiStatus_ = LoginStatus::login_in_progress;\n        UpdateWebApiUi();\n\n        try\n        {\n            const auto authScopes = qwr::unicode::ToWide( static_cast<std::string>( config::webapi_auth_scopes ) );\n            const auto authScopesSplit = qwr::string::Split<wchar_t>( authScopes, L' ' );\n            // TODO: remove me\n            WebApiAuthScopes tmp( authScopesSplit );\n            tmp.user_read_private = true;\n            auth.AuthenticateClean( tmp, [&] { ::PostMessage( m_hWnd, kOnWebApiLoginResponse, 0, 0 ); } );\n        }\n        catch ( const std::exception& e )\n        {\n            qwr::ReportErrorWithPopup( SPTF_UNDERSCORE_NAME, fmt::format( \"WebAPI login failed:\\n{}\", e.what() ) );\n\n            webApiStatus_ = LoginStatus::logged_out;\n            UpdateWebApiUi();\n        }\n    }\n    else\n    {\n        auth.ClearAuth();\n\n        webApiStatus_ = LoginStatus::logged_out;\n        UpdateWebApiUi();\n    }\n}\n\nLRESULT PreferenceTabAuth::OnWebApiLoginResponse( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled )\n{\n    (void)uMsg;\n    (void)wParam;\n    (void)lParam;\n\n    bHandled = TRUE;\n\n    auto& auth = SpotifyInstance::Get().GetWebApi_Backend().GetAuthorizer();\n\n    webApiStatus_ = ( auth.HasRefreshToken() ? LoginStatus::logged_in : LoginStatus::logged_out );\n    UpdateWebApiUi();\n\n    return 0;\n}\n\nLRESULT PreferenceTabAuth::OnStatusUpdateFinish( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled )\n{\n    (void)uMsg;\n\n    bHandled = TRUE;\n\n    libSpotifyStatus_ = ( wParam ? LoginStatus::logged_in : LoginStatus::logged_out );\n    webApiStatus_ = ( lParam ? LoginStatus::logged_in : LoginStatus::logged_out );\n    UpdateLibSpotifyUi();\n    UpdateWebApiUi();\n\n    return 0;\n}\n\nvoid PreferenceTabAuth::UpdateUiFromCfg()\n{\n    if ( !this->m_hWnd )\n    {\n        return;\n    }\n\n    for ( auto& ddxOpt: ddxOptions_ )\n    {\n        ddxOpt->Ddx().WriteToUi();\n    }\n}\n\nvoid PreferenceTabAuth::UpdateLibSpotifyUi()\n{\n    const auto getUsername = [] {\n        return SpotifyInstance::Get().GetLibSpotify_Backend().GetLoggedInUserName();\n    };\n    UpdateBackendUi( libSpotifyStatus_, btnLibSpotify_, textLibSpotify_, getUsername );\n}\n\nvoid PreferenceTabAuth::UpdateWebApiUi()\n{\n    const auto getUsername = [] {\n        qwr::TimedAbortCallback tac( fmt::format( \"{}: {}\", SPTF_UNDERSCORE_NAME, \"WebApi get username\" ) );\n        try\n        {\n            auto& waBackend = SpotifyInstance::Get().GetWebApi_Backend();\n            const auto pUser = waBackend.GetUser( tac );\n            return pUser->display_name.value_or( pUser->uri );\n        }\n        catch ( const std::exception& e )\n        {\n            return fmt::format( \"<error: user name could not be fetched - {}>\", e.what() );\n        }\n    };\n    UpdateBackendUi( webApiStatus_, btnWebApi_, textWebApi_, getUsername );\n}\n\nvoid PreferenceTabAuth::UpdateBackendUi( LoginStatus loginStatus, CButton& btn, CStatic& text, std::function<std::string()> getUserNameFn )\n{\n    Invalidate(); ///< needed to clear static text\n\n    switch ( loginStatus )\n    {\n    case LoginStatus::fetching_login_status:\n    {\n        if ( btn.IsWindowEnabled() )\n        {\n            btn.EnableWindow( FALSE );\n        }\n        btn.SetWindowText( L\"Log in\" );\n        text.SetWindowText( L\"status: verifying login status\" );\n        break;\n    }\n    case LoginStatus::logged_out:\n    {\n        if ( !btn.IsWindowEnabled() )\n        {\n            btn.EnableWindow( TRUE );\n        }\n        btn.SetWindowText( L\"Log in\" );\n        text.SetWindowText( L\"status: logged out\" );\n        break;\n    }\n    case LoginStatus::login_in_progress:\n    {\n        if ( btn.IsWindowEnabled() )\n        {\n            btn.EnableWindow( FALSE );\n        }\n        btn.SetWindowText( L\"Log in\" );\n        text.SetWindowText( L\"status: login in progress...\" );\n        break;\n    }\n    case LoginStatus::logged_in:\n    {\n        if ( !btn.IsWindowEnabled() )\n        {\n            btn.EnableWindow( TRUE );\n        }\n        btn.SetWindowText( L\"Log out\" );\n        text.SetWindowText( qwr::unicode::ToWide( fmt::format( \"status: logged in as `{}`\", getUserNameFn() ) ).c_str() );\n        break;\n    }\n    default:\n        break;\n    }\n}\n\n} // namespace sptf::ui\n"
  },
  {
    "path": "foo_spotify/ui/ui_pref_tab_auth.h",
    "content": "#pragma once\n\n#include <fb2k/config.h>\n#include <ui/ui_ipref_tab.h>\n\n#include <resource.h>\n\n#include <qwr/fb2k_config_ui_option.h>\n#include <qwr/macros.h>\n#include <qwr/ui_ddx_option.h>\n\n#include <thread>\n\nnamespace sptf::ui\n{\n\nclass PreferenceTabManager;\n\nclass PreferenceTabAuth\n    : public CDialogImpl<PreferenceTabAuth>\n    , public IPrefTab\n{\nprivate:\n    enum class LoginStatus\n    {\n        fetching_login_status,\n        logged_out,\n        login_in_progress,\n        logged_in,\n    };\n\npublic:\n    enum\n    {\n        IDD = IDD_PREF_TAB_AUTH\n    };\n\n    PreferenceTabAuth( PreferenceTabManager* pParent );\n    ~PreferenceTabAuth() override;\n\n    // IPrefTab\n    HWND CreateTab( HWND hParent ) override;\n    CDialogImplBase& Dialog() override;\n    const wchar_t* Name() const override;\n\n    t_uint32 get_state() override;\n    void apply() override;\n    void reset() override;\n\nprotected:\n    static constexpr int kOnWebApiLoginResponse = WM_USER + 1;\n    static constexpr int kOnStatusUpdateFinish = WM_USER + 2;\n\n    BEGIN_MSG_MAP( PreferenceTabAuth )\n        MSG_WM_INITDIALOG( OnInitDialog )\n        MSG_WM_DESTROY( OnDestroy )\n        MSG_WM_CTLCOLORSTATIC( OnCtlColorStatic )\n        COMMAND_HANDLER_EX( IDC_BTN_LOGIN_LIBSPOTIFY, BN_CLICKED, OnLibSpotifyLoginClick )\n        COMMAND_HANDLER_EX( IDC_BTN_LOGIN_WEBAPI, BN_CLICKED, OnWebApiLoginClick )\n        MESSAGE_HANDLER( kOnWebApiLoginResponse, OnWebApiLoginResponse )\n        MESSAGE_HANDLER( kOnStatusUpdateFinish, OnStatusUpdateFinish )\n    END_MSG_MAP()\n\nprivate:\n    BOOL OnInitDialog( HWND hwndFocus, LPARAM lParam );\n    void OnDestroy();\n\n    HBRUSH OnCtlColorStatic( CDCHandle dc, CStatic wndStatic );\n\n    void OnDdxChange( UINT uNotifyCode, int nID, CWindow wndCtl );\n    void OnLibSpotifyLoginClick( UINT uNotifyCode, int nID, CWindow wndCtl );\n    void OnWebApiLoginClick( UINT uNotifyCode, int nID, CWindow wndCtl );\n    LRESULT OnWebApiLoginResponse( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled );\n    LRESULT OnStatusUpdateFinish( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled );\n\nprivate:\n    void UpdateUiFromCfg();\n    void UpdateLibSpotifyUi();\n    void UpdateWebApiUi();\n    void UpdateBackendUi( LoginStatus loginStatus, CButton& btn, CStatic& text, std::function<std::string()> getUserNameFn );\n\nprivate:\n    PreferenceTabManager* pParent_ = nullptr;\n\n    //qwr::ui::UiOption<decltype( config::preferred_bitrate )> preferred_bitrate_;\n    std::array<std::unique_ptr<qwr::ui::IUiDdxOption>, 0> ddxOptions_;\n\n    CButton btnLibSpotify_;\n    CButton btnWebApi_;\n\n    CStatic textLibSpotify_;\n    CStatic textWebApi_;\n\n    LoginStatus libSpotifyStatus_ = LoginStatus::fetching_login_status;\n    LoginStatus webApiStatus_ = LoginStatus::fetching_login_status;\n\n    std::unique_ptr<std::thread> pStatusThread_;\n};\n\n} // namespace sptf::ui\n"
  },
  {
    "path": "foo_spotify/ui/ui_pref_tab_manager.cpp",
    "content": "#include <stdafx.h>\n\n#include \"ui_pref_tab_manager.h\"\n\n#include <fb2k/config.h>\n#include <ui/ui_pref_tab_auth.h>\n#include <ui/ui_pref_tab_playback.h>\n\n#include <component_urls.h>\n\nnamespace\n{\n\nusing namespace sptf;\n\nclass preferences_page_impl\n    : public preferences_page_v3\n{\npublic:\n    const char* get_name() override\n    {\n        return SPTF_NAME;\n    }\n\n    GUID get_guid() override\n    {\n        return guid::preferences;\n    }\n\n    GUID get_parent_guid() override\n    {\n        return preferences_page::guid_tools;\n    }\n\n    bool get_help_url( pfc::string_base& p_out ) override\n    {\n        p_out << qwr::unicode::ToU8( std::wstring_view( url::homepage ) );\n        return true;\n    }\n\n    preferences_page_instance::ptr instantiate( HWND parent, preferences_page_callback::ptr callback ) override\n    {\n        auto p = ::fb2k::service_new<ui::PreferenceTabManager>( callback );\n        p->Create( parent );\n        return p;\n    }\n};\n\npreferences_page_factory_t<preferences_page_impl> g_pref;\n\n} // namespace\n\nnamespace sptf::ui\n{\n\nusing namespace config;\n\nPreferenceTabManager::PreferenceTabManager( preferences_page_callback::ptr callback )\n    : callback_( callback )\n    , tabs_( { std::make_unique<PreferenceTabAuth>( this ),\n               std::make_unique<PreferenceTabPlayback>( this ) } )\n{\n}\n\nvoid PreferenceTabManager::OnDataChanged()\n{\n    callback_->on_state_changed();\n}\n\nHWND PreferenceTabManager::get_wnd()\n{\n    return m_hWnd;\n}\n\nt_uint32 PreferenceTabManager::get_state()\n{\n    uint32_t state = preferences_state::resettable;\n    for ( auto& tab: tabs_ )\n    {\n        state |= tab->get_state();\n    }\n\n    return state;\n}\n\nvoid PreferenceTabManager::apply()\n{\n    for ( auto& tab: tabs_ )\n    {\n        tab->apply();\n    }\n\n    OnDataChanged();\n}\n\nvoid PreferenceTabManager::reset()\n{\n    for ( auto& tab: tabs_ )\n    {\n        tab->reset();\n    }\n\n    OnDataChanged();\n}\n\nBOOL PreferenceTabManager::OnInitDialog( HWND hwndFocus, LPARAM lParam )\n{\n    cTabs_ = GetDlgItem( IDC_TAB_HOST );\n\n    for ( const auto& [i, pTab]: ranges::views::enumerate( tabs_ ) )\n    {\n        cTabs_.InsertItem( i, pTab->Name() );\n    }\n\n    cTabs_.SetCurSel( activeTabIdx_ );\n    CreateTab();\n\n    return TRUE; // set focus to default control\n}\n\nvoid PreferenceTabManager::OnParentNotify( UINT message, UINT nChildID, LPARAM lParam )\n{\n    if ( WM_DESTROY == message && pcCurTab_ && reinterpret_cast<HWND>( lParam ) == static_cast<HWND>( *pcCurTab_ ) )\n    {\n        pcCurTab_ = nullptr;\n    }\n}\n\nLRESULT PreferenceTabManager::OnSelectionChanged( LPNMHDR pNmhdr )\n{\n    activeTabIdx_ = TabCtrl_GetCurSel( GetDlgItem( IDC_TAB_HOST ) );\n    CreateTab();\n\n    return 0;\n}\n\nLRESULT PreferenceTabManager::OnWindowPosChanged( UINT, WPARAM, LPARAM lp, BOOL& bHandled )\n{\n    auto lpwp = reinterpret_cast<LPWINDOWPOS>( lp );\n    // Temporary workaround for various bugs that occur due to foobar2000 1.0+\n    // having a dislike for destroying preference pages\n    if ( lpwp->flags & SWP_HIDEWINDOW )\n    {\n        DestroyTab();\n    }\n    else if ( lpwp->flags & SWP_SHOWWINDOW && !pcCurTab_ )\n    {\n        CreateTab();\n    }\n\n    bHandled = FALSE;\n\n    return 0;\n}\n\nvoid PreferenceTabManager::CreateTab()\n{\n    DestroyTab();\n\n    RECT tabRc;\n\n    cTabs_.GetWindowRect( &tabRc );\n    ::MapWindowPoints( HWND_DESKTOP, m_hWnd, (LPPOINT)&tabRc, 2 );\n\n    cTabs_.AdjustRect( FALSE, &tabRc );\n\n    if ( activeTabIdx_ >= tabs_.size() )\n    {\n        activeTabIdx_ = 0;\n    }\n\n    auto& pCurTab = tabs_[activeTabIdx_];\n    pcCurTab_ = &pCurTab->Dialog();\n    pCurTab->CreateTab( m_hWnd );\n\n    EnableThemeDialogTexture( *pcCurTab_, ETDT_ENABLETAB );\n\n    pcCurTab_->SetWindowPos( nullptr, tabRc.left, tabRc.top, tabRc.right - tabRc.left, tabRc.bottom - tabRc.top, SWP_NOZORDER );\n    cTabs_.SetWindowPos( HWND_BOTTOM, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE );\n\n    pcCurTab_->ShowWindow( SW_SHOWNORMAL );\n}\n\nvoid PreferenceTabManager::DestroyTab()\n{\n    if ( pcCurTab_ && *pcCurTab_ )\n    {\n        pcCurTab_->ShowWindow( SW_HIDE );\n        pcCurTab_->DestroyWindow();\n    }\n}\n\n} // namespace sptf::ui\n"
  },
  {
    "path": "foo_spotify/ui/ui_pref_tab_manager.h",
    "content": "#pragma once\n\n#include <ui/ui_ipref_tab.h>\n\n#include <resource.h>\n\n#include <array>\n\nnamespace sptf::ui\n{\n\nclass PreferenceTabMain;\n\nclass PreferenceTabManager\n    : public CDialogImpl<PreferenceTabManager>\n    , public CWinDataExchange<PreferenceTabManager>\n    , public preferences_page_instance\n{\npublic:\n    enum\n    {\n        IDD = IDD_PREF_TAB_HOST\n    };\n\n    BEGIN_MSG_MAP( PreferenceTabManager )\n        MSG_WM_INITDIALOG( OnInitDialog )\n        MSG_WM_PARENTNOTIFY( OnParentNotify )\n        MESSAGE_HANDLER( WM_WINDOWPOSCHANGED, OnWindowPosChanged )\n        NOTIFY_HANDLER_EX( IDC_TAB_HOST, TCN_SELCHANGE, OnSelectionChanged )\n    END_MSG_MAP()\n\npublic:\n    PreferenceTabManager( preferences_page_callback::ptr callback );\n\n    void OnDataChanged();\n\n    // preferences_page_instance\n    HWND get_wnd() override;\n    t_uint32 get_state() override;\n    void apply() override;\n    void reset() override;\n\nprivate:\n    BOOL OnInitDialog( HWND hwndFocus, LPARAM lParam );\n    void OnParentNotify( UINT message, UINT nChildID, LPARAM lParam );\n    LRESULT OnWindowPosChanged( UINT, WPARAM, LPARAM lp, BOOL& bHandled );\n    LRESULT OnSelectionChanged( LPNMHDR pNmhdr );\n\n    void CreateTab();\n    void DestroyTab();\n\nprivate:\n    preferences_page_callback::ptr callback_;\n\n    CTabCtrl cTabs_;\n    CDialogImplBase* pcCurTab_ = nullptr;\n\n    size_t activeTabIdx_ = 0;\n    std::array<std::unique_ptr<IPrefTab>, 2> tabs_;\n};\n\n} // namespace sptf::ui\n"
  },
  {
    "path": "foo_spotify/ui/ui_pref_tab_playback.cpp",
    "content": "#include <stdafx.h>\n\n#include \"ui_pref_tab_playback.h\"\n\n#include <backend/libspotify_backend.h>\n#include <backend/spotify_instance.h>\n#include <backend/webapi_auth.h>\n#include <backend/webapi_auth_scopes.h>\n#include <backend/webapi_backend.h>\n#include <backend/webapi_objects/webapi_user.h>\n#include <fb2k/config.h>\n#include <ui/ui_pref_tab_manager.h>\n\n#include <component_urls.h>\n\n#include <qwr/abort_callback.h>\n#include <qwr/error_popup.h>\n#include <qwr/final_action.h>\n#include <qwr/string_helpers.h>\n\nnamespace\n{\n\nint GetNearestScrollPos( float curValue, int direction )\n{\n    if ( auto curShift = curValue - std::floor( curValue );\n         !curShift )\n    {\n        return (int)( curValue + direction );\n    }\n    else\n    {\n        if ( direction < 0 )\n        {\n            return (int)std::floor( curValue );\n        }\n        else if ( direction > 0 )\n        {\n            return (int)std::ceil( curValue );\n        }\n        else\n        {\n            return (int)std::round( curValue );\n        }\n    }\n}\n\n} // namespace\n\nnamespace sptf::ui\n{\n\nPreferenceTabPlayback::PreferenceTabPlayback( PreferenceTabManager* pParent )\n    : pParent_( pParent )\n    , trackToEdit_( { { IDC_SLIDER_CACHE_PERCENT, IDC_EDIT_CACHE_PERCENT },\n                      { IDC_SLIDER_CACHE_MB, IDC_EDIT_CACHE_MB } } )\n    , editToTrack_( { { IDC_EDIT_CACHE_PERCENT, IDC_SLIDER_CACHE_PERCENT },\n                      { IDC_EDIT_CACHE_MB, IDC_SLIDER_CACHE_MB } } )\n    , enable_normalization_( config::enable_normalization )\n    , enable_private_mode_( config::enable_private_mode )\n    , libspotify_cache_size_in_percent_( config::libspotify_cache_size_in_percent )\n    , libspotify_cache_size_in_mb_( config::libspotify_cache_size_in_mb )\n    , preferred_bitrate_(\n          config::preferred_bitrate,\n          { { config::BitrateSettings::Bitrate96k, 0 },\n            { config::BitrateSettings::Bitrate160k, 1 },\n            { config::BitrateSettings::Bitrate320k, 2 } } )\n    , ddxOptions_(\n          { qwr::ui::CreateUiDdxOption<qwr::ui::UiDdx_CheckBox>( enable_normalization_, IDC_CHECK_NORMALIZE ),\n            qwr::ui::CreateUiDdxOption<qwr::ui::UiDdx_CheckBox>( enable_private_mode_, IDC_CHECK_PRIVATE ),\n            qwr::ui::CreateUiDdxOption<qwr::ui::UiDdx_TrackBar>( libspotify_cache_size_in_percent_, IDC_SLIDER_CACHE_PERCENT ),\n            qwr::ui::CreateUiDdxOption<qwr::ui::UiDdx_TrackBar>( libspotify_cache_size_in_mb_, IDC_SLIDER_CACHE_MB ),\n            qwr::ui::CreateUiDdxOption<qwr::ui::UiDdx_ComboBox>( preferred_bitrate_, IDC_COMBO_BITRATE ) } )\n{\n}\n\nPreferenceTabPlayback::~PreferenceTabPlayback()\n{\n    for ( auto& ddxOpt: ddxOptions_ )\n    {\n        ddxOpt->Option().Revert();\n    }\n}\n\nHWND PreferenceTabPlayback::CreateTab( HWND hParent )\n{\n    return Create( hParent );\n}\n\nCDialogImplBase& PreferenceTabPlayback::Dialog()\n{\n    return *this;\n}\n\nconst wchar_t* PreferenceTabPlayback::Name() const\n{\n    return L\"Playback\";\n}\n\nt_uint32 PreferenceTabPlayback::get_state()\n{\n    const bool hasChanged =\n        ddxOptions_.cend() != std::find_if( ddxOptions_.cbegin(), ddxOptions_.cend(), []( const auto& ddxOpt ) {\n            return ddxOpt->Option().HasChanged();\n        } );\n\n    return ( preferences_state::resettable | ( hasChanged ? preferences_state::changed : 0 ) );\n}\n\nvoid PreferenceTabPlayback::apply()\n{\n    for ( auto& ddxOpt: ddxOptions_ )\n    {\n        ddxOpt->Option().Apply();\n    }\n\n    RefreshLibSpotifySettings();\n\n    pParent_->OnDataChanged();\n}\n\nvoid PreferenceTabPlayback::reset()\n{\n    for ( auto& ddxOpt: ddxOptions_ )\n    {\n        ddxOpt->Option().ResetToDefault();\n    }\n    DoFullDdxToUi();\n\n    pParent_->OnDataChanged();\n}\n\nBOOL PreferenceTabPlayback::OnInitDialog( HWND hwndFocus, LPARAM lParam )\n{\n    CComboBox comboBitrate( GetDlgItem( IDC_COMBO_BITRATE ) );\n    comboBitrate.AddString( L\"96 kbit/s\" );\n    comboBitrate.AddString( L\"160 kbit/s\" );\n    comboBitrate.AddString( L\"320 kbit/s\" );\n\n    CTrackBarCtrl trackCacheMb( GetDlgItem( IDC_SLIDER_CACHE_MB ) );\n    trackCacheMb.SetRangeMin( 0 );\n    trackCacheMb.SetRangeMax( 8192 );\n    trackCacheMb.SetTicFreq( 512 );\n\n    CTrackBarCtrl trackCachePercent( GetDlgItem( IDC_SLIDER_CACHE_PERCENT ) );\n    trackCachePercent.SetRangeMin( 0 );\n    trackCachePercent.SetRangeMax( 100 );\n    trackCachePercent.SetTicFreq( 5 );\n\n    for ( auto& ddxOpt: ddxOptions_ )\n    {\n        ddxOpt->Ddx().SetHwnd( m_hWnd );\n    }\n    DoFullDdxToUi();\n\n    this->SetDlgItemInt( IDC_EDIT_CACHE_MB, libspotify_cache_size_in_mb_, false );\n    this->SetDlgItemInt( IDC_EDIT_CACHE_PERCENT, libspotify_cache_size_in_percent_, false );\n\n    suppressUiDdx_ = false;\n\n    return TRUE; // set focus to default control\n}\n\nvoid PreferenceTabPlayback::OnDdxUiChange( UINT uNotifyCode, int nID, CWindow wndCtl )\n{\n    if ( suppressUiDdx_ )\n    {\n        return;\n    }\n\n    auto it = std::find_if( ddxOptions_.begin(), ddxOptions_.end(), [nID]( auto& val ) {\n        return val->Ddx().IsMatchingId( nID );\n    } );\n\n    if ( ddxOptions_.end() != it )\n    {\n        ( *it )->Ddx().ReadFromUi();\n        pParent_->OnDataChanged();\n    }\n}\n\nvoid PreferenceTabPlayback::OnDdxValueChange( int nID )\n{\n    // avoid triggering loopback ddx\n    suppressUiDdx_ = true;\n    const qwr::final_action autoSuppress( [&] { suppressUiDdx_ = false; } );\n\n    auto it = std::find_if( ddxOptions_.begin(), ddxOptions_.end(), [nID]( auto& val ) {\n        return val->Ddx().IsMatchingId( nID );\n    } );\n\n    assert( ddxOptions_.end() != it );\n    ( *it )->Ddx().WriteToUi();\n}\n\nLRESULT PreferenceTabPlayback::OnTrackBarPosChangedNotify( LPNMHDR pnmh )\n{\n    auto pNMTR = reinterpret_cast<NMTRBTHUMBPOSCHANGING*>( pnmh );\n    if ( pNMTR->nReason == TB_ENDTRACK )\n    {\n        return 1;\n    }\n\n    if ( suppressUiDdx_ )\n    {\n        return 1;\n    }\n\n    const auto id = pNMTR->hdr.idFrom;\n\n    CTrackBarCtrl trackBar( GetDlgItem( id ) );\n    const auto tickCount = trackBar.GetNumTics() - 1;\n    const auto rangeMin = trackBar.GetRangeMin();\n    const auto rangeMax = trackBar.GetRangeMax();\n    const auto tickFreq = ( rangeMax - rangeMin ) / tickCount;\n    const auto prevPos = trackBar.GetPos();\n    const auto pos = pNMTR->dwPos;\n\n    auto adjustedPos = [&] {\n        const auto ticks = (float)pos / tickFreq;\n        const auto diffSign = ( (int)pos - (int)prevPos < 0 ? -1 : 1 );\n        switch ( pNMTR->nReason )\n        {\n        case TB_PAGEUP:\n        case TB_PAGEDOWN:\n        {\n            const auto diffTicks = std::abs( (int)pos - (int)prevPos ) / (int)tickFreq;\n            return ( GetNearestScrollPos( ticks, diffSign ) + diffSign * diffTicks ) * (int)tickFreq;\n        }\n        case TB_LINEUP:\n        case TB_LINEDOWN:\n        {\n            return GetNearestScrollPos( ticks, diffSign ) * (int)tickFreq;\n        }\n        case TB_THUMBTRACK:\n        case TB_THUMBPOSITION:\n        { // snap to the closest\n            return GetNearestScrollPos( ticks, 0 ) * (int)tickFreq;\n        }\n        default:\n        {\n            return (int)pos;\n        }\n        }\n    }();\n    adjustedPos = std::clamp( adjustedPos, rangeMin, rangeMax );\n\n    tracksRedrawing_.emplace( id );\n    trackBar.SetPos( adjustedPos );\n    OnDdxUiChange( 0, id, nullptr );\n\n    // avoid triggering ddx for linked edit\n    suppressUiDdx_ = true;\n    const qwr::final_action autoSuppress( [&] { suppressUiDdx_ = false; } );\n\n    this->SetDlgItemInt( trackToEdit_.at( id ), adjustedPos, false );\n\n    return 1;\n}\n\nvoid PreferenceTabPlayback::OnTrackBarHScroll( UINT nSBCode, UINT nPos, CTrackBarCtrl trackBar )\n{\n    if ( nSBCode == TB_ENDTRACK )\n    {\n        return;\n    }\n\n    const auto trackId = trackBar.GetDlgCtrlID();\n    if ( tracksRedrawing_.count( trackId ) )\n    {\n        tracksRedrawing_.erase( trackId );\n        return;\n    }\n\n    // some events are not processed by TRBN_THUMBPOSCHANGING\n\n    const auto pos = trackBar.GetPos();\n    OnDdxUiChange( 0, trackId, nullptr );\n\n    // avoid triggering ddx for linked edit\n    suppressUiDdx_ = true;\n    const qwr::final_action autoSuppress( [&] { suppressUiDdx_ = false; } );\n\n    this->SetDlgItemInt( trackToEdit_.at( trackId ), pos, false );\n}\n\nvoid PreferenceTabPlayback::OnTrackBarEdit( UINT uNotifyCode, int nID, CWindow wndCtl )\n{\n    if ( suppressUiDdx_ )\n    {\n        return;\n    }\n\n    BOOL lpTrans;\n    const auto editPosRaw = this->GetDlgItemInt( nID, &lpTrans, false );\n    if ( !lpTrans )\n    {\n        return;\n    }\n\n    const auto trackId = editToTrack_.at( nID );\n    CTrackBarCtrl trackbar( GetDlgItem( trackId ) );\n    const auto editPos = std::clamp<int>( editPosRaw, trackbar.GetRangeMin(), trackbar.GetRangeMax() );\n    if ( editPos != editPosRaw )\n    {\n        this->SetDlgItemInt( nID, editPos, false );\n    }\n\n    if ( trackbar.GetPos() == editPos )\n    {\n        return;\n    }\n\n    switch ( trackId )\n    {\n    case IDC_SLIDER_CACHE_MB:\n        libspotify_cache_size_in_mb_ = editPos;\n        break;\n    case IDC_SLIDER_CACHE_PERCENT:\n        libspotify_cache_size_in_percent_ = editPos;\n        break;\n    default:\n        assert( false );\n        break;\n    }\n\n    OnDdxValueChange( trackId );\n}\n\nvoid PreferenceTabPlayback::DoFullDdxToUi()\n{\n    if ( !this->m_hWnd )\n    {\n        return;\n    }\n\n    for ( auto& ddxOpt: ddxOptions_ )\n    {\n        ddxOpt->Ddx().WriteToUi();\n    }\n}\n\nvoid PreferenceTabPlayback::RefreshLibSpotifySettings()\n{\n    auto& lsBackend = SpotifyInstance::Get().GetLibSpotify_Backend();\n    lsBackend.RefreshBitrate();\n    lsBackend.RefreshNormalization();\n    lsBackend.RefreshPrivateMode();\n    lsBackend.RefreshCacheSize();\n}\n\n} // namespace sptf::ui\n"
  },
  {
    "path": "foo_spotify/ui/ui_pref_tab_playback.h",
    "content": "#pragma once\n\n#include <fb2k/config.h>\n#include <ui/ui_ipref_tab.h>\n\n#include <resource.h>\n\n#include <qwr/fb2k_config_ui_option.h>\n#include <qwr/macros.h>\n#include <qwr/ui_ddx_option.h>\n\n#include <thread>\n#include <unordered_map>\n#include <unordered_set>\n\nnamespace sptf::ui\n{\n\nclass PreferenceTabManager;\n\nclass PreferenceTabPlayback\n    : public CDialogImpl<PreferenceTabPlayback>\n    , public IPrefTab\n{\npublic:\n    enum\n    {\n        IDD = IDD_PREF_TAB_PLAYBACK\n    };\n\n    PreferenceTabPlayback( PreferenceTabManager* pParent );\n    ~PreferenceTabPlayback() override;\n\n    // IPrefTab\n    HWND CreateTab( HWND hParent ) override;\n    CDialogImplBase& Dialog() override;\n    const wchar_t* Name() const override;\n\n    t_uint32 get_state() override;\n    void apply() override;\n    void reset() override;\n\nprotected:\n    BEGIN_MSG_MAP( PreferenceTabPlayback )\n        MSG_WM_INITDIALOG( OnInitDialog )\n        MSG_WM_HSCROLL( OnTrackBarHScroll )\n        COMMAND_HANDLER_EX( IDC_COMBO_BITRATE, CBN_SELCHANGE, OnDdxUiChange )\n        COMMAND_HANDLER_EX( IDC_CHECK_NORMALIZE, BN_CLICKED, OnDdxUiChange )\n        COMMAND_HANDLER_EX( IDC_CHECK_PRIVATE, BN_CLICKED, OnDdxUiChange )\n        NOTIFY_HANDLER_EX( IDC_SLIDER_CACHE_MB, TRBN_THUMBPOSCHANGING, OnTrackBarPosChangedNotify )\n        NOTIFY_HANDLER_EX( IDC_SLIDER_CACHE_PERCENT, TRBN_THUMBPOSCHANGING, OnTrackBarPosChangedNotify )\n        COMMAND_HANDLER_EX( IDC_EDIT_CACHE_MB, EN_CHANGE, OnTrackBarEdit )\n        COMMAND_HANDLER_EX( IDC_EDIT_CACHE_PERCENT, EN_CHANGE, OnTrackBarEdit )\n    END_MSG_MAP()\n\nprivate:\n    BOOL OnInitDialog( HWND hwndFocus, LPARAM lParam );\n\n    void OnDdxUiChange( UINT uNotifyCode, int nID, CWindow wndCtl );\n    void OnDdxValueChange( int nID );\n\n    LRESULT OnTrackBarPosChangedNotify( LPNMHDR pnmh );\n    void OnTrackBarHScroll( UINT nSBCode, UINT nPos, CTrackBarCtrl trackBar );\n    void OnTrackBarEdit( UINT uNotifyCode, int nID, CWindow wndCtl );\n\n    void DoFullDdxToUi();\n\n    void RefreshLibSpotifySettings();\n\nprivate:\n    PreferenceTabManager* pParent_ = nullptr;\n\n    std::unordered_map<int, int> trackToEdit_;\n    std::unordered_map<int, int> editToTrack_;\n    std::unordered_set<int> tracksRedrawing_;\n\n    bool suppressUiDdx_ = true;\n\n#define SPTF_DEFINE_UI_OPTION( name ) \\\n    qwr::ui::UiOption<decltype( config::name )> name##_;\n\n#define SPTF_DEFINE_UI_OPTIONS( ... ) \\\n    QWR_EXPAND( QWR_PASTE( SPTF_DEFINE_UI_OPTION, __VA_ARGS__ ) )\n\n    SPTF_DEFINE_UI_OPTIONS( enable_normalization,\n                            enable_private_mode,\n                            libspotify_cache_size_in_percent,\n                            libspotify_cache_size_in_mb,\n                            preferred_bitrate )\n\n#undef SPTF_DEFINE_OPTIONS\n#undef SPTF_DEFINE_OPTION\n\n    std::array<std::unique_ptr<qwr::ui::IUiDdxOption>, 5> ddxOptions_;\n};\n\n} // namespace sptf::ui\n"
  },
  {
    "path": "foo_spotify/utils/abort_manager.cpp",
    "content": "#include <stdafx.h>\n\n#include \"abort_manager.h\"\n\n#include <qwr/thread_helpers.h>\n\nnamespace sptf\n{\n\nAbortManager::AbortManager()\n{\n    StartThread();\n}\n\nvoid AbortManager::Finalize()\n{\n    StopThread();\n}\n\nvoid AbortManager::RemoveTask( uint32_t taskId )\n{\n    std::unique_lock lock( mutex_ );\n\n    const auto itTask = idToTask_.find( taskId );\n    assert( itTask != idToTask_.cend() );\n    const auto pAbort = itTask->second.pAbort;\n    idToTask_.erase( itTask );\n\n    const auto itIds = abortToIds_.find( pAbort );\n    assert( itIds != abortToIds_.cend() );\n    auto& ids = itIds->second;\n\n    const auto itId = std::find( ids.rbegin(), ids.rend(), taskId );\n    assert( itId != ids.rend() );\n\n    ids.erase( std::next( itId ).base() );\n    if ( ids.empty() )\n    {\n        abortToIds_.erase( itIds );\n    }\n\n    assert( abortToIds_.size() <= idToTask_.size() );\n}\n\nvoid AbortManager::StartThread()\n{\n    pThread_ = std::make_unique<std::thread>( &AbortManager::EventLoop, this );\n    qwr::SetThreadName( *pThread_, \"SPTF Abort Handler\" );\n}\n\nvoid AbortManager::StopThread()\n{\n    if ( !pThread_ )\n    {\n        return;\n    }\n\n    {\n        std::unique_lock lock( mutex_ );\n        isTimeToDie_ = true;\n    }\n    eventCv_.notify_all();\n\n    if ( pThread_->joinable() )\n    {\n        pThread_->join();\n    }\n\n    pThread_.reset();\n}\n\nvoid AbortManager::EventLoop()\n{\n    while ( true )\n    {\n        std::unique_lock lock( mutex_ );\n\n        do\n        {\n            eventCv_.wait_for( lock, std::chrono::seconds( 2 ) );\n        } while ( !isTimeToDie_ && abortToIds_.empty() );\n\n        if ( isTimeToDie_ )\n        {\n            for ( auto& [id, task]: idToTask_ )\n            {\n                std::invoke( *( task.task ) );\n            }\n            return;\n        }\n\n        for ( const auto& [pAbort, ids]: abortToIds_ )\n        {\n            if ( pAbort->is_aborting() )\n            {\n                for ( const auto& id: ranges::views::reverse( ids ) )\n                {\n                    assert( idToTask_.count( id ) );\n                    std::invoke( *( idToTask_[id].task ) );\n                }\n            }\n        }\n    }\n}\n\nAbortManager::AbortableScope::AbortableScope( size_t taskId, AbortManager& parent )\n    : parent_( parent )\n    , taskId_( taskId )\n{\n}\n\nAbortManager::AbortableScope::AbortableScope( AbortableScope&& other )\n    : parent_( other.parent_ )\n    , isValid_( other.isValid_ )\n    , taskId_( other.taskId_ )\n{\n    other.isValid_ = false;\n}\n\nAbortManager::AbortableScope::~AbortableScope()\n{\n    if ( isValid_ )\n    {\n        parent_.RemoveTask( taskId_ );\n    }\n}\n\n} // namespace sptf\n"
  },
  {
    "path": "foo_spotify/utils/abort_manager.h",
    "content": "#pragma once\n\n#include <condition_variable>\n#include <functional>\n#include <mutex>\n\nnamespace sptf\n{\n\nclass AbortManager\n{\nprivate:\n    using Task = std::function<void()>;\n\n    struct AbortableTask\n    {\n        std::unique_ptr<Task> task;\n        abort_callback* pAbort;\n    };\n\npublic:\n    class AbortableScope\n    {\n        friend class AbortManager;\n\n    public:\n        AbortableScope( AbortableScope&& other );\n        ~AbortableScope();\n\n    private:\n        AbortableScope( size_t taskId, AbortManager& parent );\n\n    private:\n        AbortManager& parent_;\n        bool isValid_ = true;\n        size_t taskId_;\n    };\n\npublic:\n    AbortManager();\n    AbortManager( const AbortManager& other ) = delete;\n    AbortManager( AbortManager&& other ) = delete;\n    ~AbortManager() = default;\n\n    void Finalize();\n\n    template <typename T>\n    AbortableScope GetAbortableScope( T&& task, abort_callback& abort )\n    {\n        return AbortableScope( AddTask( std::forward<T>( task ), abort ), *this );\n    }\n\nprivate:\n    void StartThread();\n    void StopThread();\n\n    void EventLoop();\n\n    template <typename T>\n    size_t AddTask( T&& task, abort_callback& abort )\n    {\n        static_assert( std::is_invocable_v<T> );\n        static_assert( std::is_move_constructible_v<T> || std::is_copy_constructible_v<T> );\n\n        const auto taskId = [&] {\n            std::unique_lock lock( mutex_ );\n\n            const auto taskId = [&] {\n                auto id = idCounter_;\n                while ( idToTask_.count( id ) )\n                {\n                    id = ++idCounter_;\n                }\n                return id;\n            }();\n\n            if constexpr ( !std::is_copy_constructible_v<T> && std::is_move_constructible_v<T> )\n            {\n                auto taskLambda = [taskWrapper = std::make_shared<T>( std::forward<T>( task ) )] {\n                    std::invoke( *taskWrapper );\n                };\n                idToTask_.try_emplace( taskId, AbortableTask{ std::make_unique<Task>( taskLambda ), &abort } );\n            }\n            else\n            {\n                idToTask_.try_emplace( taskId, AbortableTask{ std::make_unique<Task>( std::forward<T>( task ) ), &abort } );\n            }\n\n            return abortToIds_[&abort].emplace_back( taskId );\n        }();\n\n        eventCv_.notify_all();\n\n        return taskId;\n    }\n\n    void RemoveTask( uint32_t taskId );\n\nprivate:\n    std::unique_ptr<std::thread> pThread_;\n\n    std::mutex mutex_;\n    std::condition_variable eventCv_;\n    bool isTimeToDie_ = false;\n\n    size_t idCounter_ = 0;\n    std::unordered_map<size_t, AbortableTask> idToTask_;\n    std::unordered_map<abort_callback*, std::vector<size_t>> abortToIds_;\n};\n\n} // namespace sptf\n"
  },
  {
    "path": "foo_spotify/utils/async_mutex.hpp",
    "content": "///////////////////////////////////////////////////////////////////////////////\n// Copyright (c) Lewis Baker\n// Licenced under MIT license. See LICENSE.txt for details.\n///////////////////////////////////////////////////////////////////////////////\n#ifndef CPPCORO_ASYNC_MUTEX_HPP_INCLUDED\n#define CPPCORO_ASYNC_MUTEX_HPP_INCLUDED\n\n#include <atomic>\n#include <cstdint>\n#include <mutex> // for std::adopt_lock_t\n\n#include <experimental/coroutine>\n\nnamespace cppcoro\n{\nclass async_mutex_lock;\nclass async_mutex_lock_operation;\nclass async_mutex_scoped_lock_operation;\n\n/// \\brief\n/// A mutex that can be locked asynchronously using 'co_await'.\n///\n/// Ownership of the mutex is not tied to any particular thread.\n/// This allows the coroutine owning the lock to transition from\n/// one thread to another while holding a lock.\n///\n/// Implementation is lock-free, using only std::atomic values for\n/// synchronisation. Awaiting coroutines are suspended without blocking\n/// the current thread if the lock could not be acquired synchronously.\nclass async_mutex\n{\npublic:\n    /// \\brief\n    /// Construct to a mutex that is not currently locked.\n    async_mutex() noexcept;\n\n    /// Destroys the mutex.\n    ///\n    /// Behaviour is undefined if there are any outstanding coroutines\n    /// still waiting to acquire the lock.\n    ~async_mutex();\n\n    /// \\brief\n    /// Attempt to acquire a lock on the mutex without blocking.\n    ///\n    /// \\return\n    /// true if the lock was acquired, false if the mutex was already locked.\n    /// The caller is responsible for ensuring unlock() is called on the mutex\n    /// to release the lock if the lock was acquired by this call.\n    bool try_lock() noexcept;\n\n    /// \\brief\n    /// Acquire a lock on the mutex asynchronously.\n    ///\n    /// If the lock could not be acquired synchronously then the awaiting\n    /// coroutine will be suspended and later resumed when the lock becomes\n    /// available. If suspended, the coroutine will be resumed inside the\n    /// call to unlock() from the previous lock owner.\n    ///\n    /// \\return\n    /// An operation object that must be 'co_await'ed to wait until the\n    /// lock is acquired. The result of the 'co_await m.lock_async()'\n    /// expression has type 'void'.\n    async_mutex_lock_operation lock_async() noexcept;\n\n    /// \\brief\n    /// Acquire a lock on the mutex asynchronously, returning an object that\n    /// will call unlock() automatically when it goes out of scope.\n    ///\n    /// If the lock could not be acquired synchronously then the awaiting\n    /// coroutine will be suspended and later resumed when the lock becomes\n    /// available. If suspended, the coroutine will be resumed inside the\n    /// call to unlock() from the previous lock owner.\n    ///\n    /// \\return\n    /// An operation object that must be 'co_await'ed to wait until the\n    /// lock is acquired. The result of the 'co_await m.scoped_lock_async()'\n    /// expression returns an 'async_mutex_lock' object that will call\n    /// this->mutex() when it destructs.\n    async_mutex_scoped_lock_operation scoped_lock_async() noexcept;\n\n    /// \\brief\n    /// Unlock the mutex.\n    ///\n    /// Must only be called by the current lock-holder.\n    ///\n    /// If there are lock operations waiting to acquire the\n    /// mutex then the next lock operation in the queue will\n    /// be resumed inside this call.\n    void unlock();\n\nprivate:\n    friend class async_mutex_lock_operation;\n\n    static constexpr std::uintptr_t not_locked = 1;\n\n    // assume == reinterpret_cast<std::uintptr_t>(static_cast<void*>(nullptr))\n    static constexpr std::uintptr_t locked_no_waiters = 0;\n\n    // This field provides synchronisation for the mutex.\n    //\n    // It can have three kinds of values:\n    // - not_locked\n    // - locked_no_waiters\n    // - a pointer to the head of a singly linked list of recently\n    //   queued async_mutex_lock_operation objects. This list is\n    //   in most-recently-queued order as new items are pushed onto\n    //   the front of the list.\n    std::atomic<std::uintptr_t> m_state;\n\n    // Linked list of async lock operations that are waiting to acquire\n    // the mutex. These operations will acquire the lock in the order\n    // they appear in this list. Waiters in this list will acquire the\n    // mutex before waiters added to the m_newWaiters list.\n    async_mutex_lock_operation* m_waiters;\n};\n\n/// \\brief\n/// An object that holds onto a mutex lock for its lifetime and\n/// ensures that the mutex is unlocked when it is destructed.\n///\n/// It is equivalent to a std::lock_guard object but requires\n/// that the result of co_await async_mutex::lock_async() is\n/// passed to the constructor rather than passing the async_mutex\n/// object itself.\nclass async_mutex_lock\n{\npublic:\n    explicit async_mutex_lock( async_mutex& mutex, std::adopt_lock_t ) noexcept\n        : m_mutex( &mutex )\n    {\n    }\n\n    async_mutex_lock( async_mutex_lock&& other ) noexcept\n        : m_mutex( other.m_mutex )\n    {\n        other.m_mutex = nullptr;\n    }\n\n    async_mutex_lock( const async_mutex_lock& other ) = delete;\n    async_mutex_lock& operator=( const async_mutex_lock& other ) = delete;\n\n    // Releases the lock.\n    ~async_mutex_lock()\n    {\n        if ( m_mutex != nullptr )\n        {\n            m_mutex->unlock();\n        }\n    }\n\nprivate:\n    async_mutex* m_mutex;\n};\n\nclass async_mutex_lock_operation\n{\npublic:\n    explicit async_mutex_lock_operation( async_mutex& mutex ) noexcept\n        : m_mutex( mutex )\n    {\n    }\n\n    bool await_ready() const noexcept\n    {\n        return false;\n    }\n    bool await_suspend( std::experimental::coroutine_handle<> awaiter ) noexcept;\n    void await_resume() const noexcept\n    {\n    }\n\nprotected:\n    friend class async_mutex;\n\n    async_mutex& m_mutex;\n\nprivate:\n    async_mutex_lock_operation* m_next;\n    std::experimental::coroutine_handle<> m_awaiter;\n};\n\nclass async_mutex_scoped_lock_operation : public async_mutex_lock_operation\n{\npublic:\n    using async_mutex_lock_operation::async_mutex_lock_operation;\n\n    [[nodiscard]] async_mutex_lock await_resume() const noexcept\n    {\n        return async_mutex_lock{ m_mutex, std::adopt_lock };\n    }\n};\n} // namespace cppcoro\n\n#endif\n"
  },
  {
    "path": "foo_spotify/utils/cred_prompt.cpp",
    "content": "#include <stdafx.h>\n\n#include \"cred_prompt.h\"\n\n#include <Ntsecapi.h>\n#include <WinCred.h>\n\nnamespace sptf\n{\n\nstd::unique_ptr<CredentialsResult> ShowCredentialsDialog( HWND hWnd, const char* msg )\n{\n    const auto wMsg = [msg]\n    {\n        if (msg)\n        {\n            auto ret = qwr::unicode::ToWide( std::string_view{ msg } );\n            if ( ret.size() > CREDUI_MAX_MESSAGE_LENGTH )\n            {\n                ret.resize( CREDUI_MAX_MESSAGE_LENGTH );\n                ret[CREDUI_MAX_MESSAGE_LENGTH - 3] = L'.';\n                ret[CREDUI_MAX_MESSAGE_LENGTH - 2] = L'.';\n                ret[CREDUI_MAX_MESSAGE_LENGTH - 1] = L'.';\n            }\n            return ret;\n        }\n        else\n        {\n            return std::wstring( L\"Please enter your Spotify username and password.\" );\n        }\n    }();\n\n    CREDUI_INFOW cui{};\n    cui.cbSize = sizeof( CREDUI_INFO );\n    cui.hwndParent = hWnd;\n    //  Ensure that MessageText and CaptionText identify what credentials\n    //  to use and which application requires them.\n    cui.pszMessageText = wMsg.c_str();\n    cui.pszCaptionText = L\"Sign in to Spotify\";\n    BOOL fSave = FALSE;\n\n    SecureVector<wchar_t> pszName( CREDUI_MAX_USERNAME_LENGTH + 1 );\n    SecureVector<wchar_t> pszPwd( CREDUI_MAX_PASSWORD_LENGTH + 1 );\n\n    const DWORD dwErr = CredUIPromptForCredentialsW(\n        &cui,                              // CREDUI_INFO structure\n        TEXT( SPTF_UNDERSCORE_NAME ),      // Target for credentials\n        nullptr,                           // Reserved\n        0,                                 // Reason\n        pszName.data(),                    // User name\n        pszName.size(),                    // Max number of char for user name\n        pszPwd.data(),                     // Password\n        pszPwd.size(),                     // Max number of char for password\n        &fSave,                            // State of save check box\n        CREDUI_FLAGS_GENERIC_CREDENTIALS | // flags\n            CREDUI_FLAGS_ALWAYS_SHOW_UI | CREDUI_FLAGS_DO_NOT_PERSIST );\n\n    auto cpr = std::make_unique<CredentialsResult>();\n    if ( dwErr == NO_ERROR )\n    {\n        const auto wtou = []( const auto& in, auto& out ) {\n            size_t stringLen = WideCharToMultiByte( CP_UTF8, 0, in.data(), in.size(), nullptr, 0, nullptr, nullptr );\n            out.resize( stringLen );\n\n            stringLen = WideCharToMultiByte( CP_UTF8, 0, in.data(), in.size(), out.data(), out.size(), nullptr, nullptr );\n            out.resize( stringLen );\n        };\n\n        wtou( pszName, cpr->un );\n        wtou( pszPwd, cpr->pw );\n    }\n    else if ( dwErr == ERROR_CANCELLED )\n    {\n        cpr->cancelled = true;\n    }\n    return cpr;\n}\n\n} // namespace sptf\n"
  },
  {
    "path": "foo_spotify/utils/cred_prompt.h",
    "content": "#pragma once\n\n#include <utils/secure_vector.h>\n\nnamespace sptf\n{\n\nstruct CredentialsResult\n{\n    SecureVector<char> un;\n    SecureVector<char> pw;\n    bool cancelled = false;\n};\n\nstd::unique_ptr<CredentialsResult> ShowCredentialsDialog( HWND hWnd, const char* msg );\n\n} // namespace sptf\n"
  },
  {
    "path": "foo_spotify/utils/json_macro_fix.h",
    "content": "#pragma once\n\n// same as the stock one, but without `inline`\n#define SPTF_NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE( Type, ... )                           \\\n    void to_json( nlohmann::json& nlohmann_json_j, const Type& nlohmann_json_t )       \\\n    {                                                                                  \\\n        NLOHMANN_JSON_EXPAND( NLOHMANN_JSON_PASTE( NLOHMANN_JSON_TO, __VA_ARGS__ ) )   \\\n    }                                                                                  \\\n    void from_json( const nlohmann::json& nlohmann_json_j, Type& nlohmann_json_t )     \\\n    {                                                                                  \\\n        NLOHMANN_JSON_EXPAND( NLOHMANN_JSON_PASTE( NLOHMANN_JSON_FROM, __VA_ARGS__ ) ) \\\n    }\n"
  },
  {
    "path": "foo_spotify/utils/json_std_extenders.h",
    "content": "#include <memory>\n\nnamespace nlohmann\n{\ntemplate <typename T>\nstruct adl_serializer<std::unique_ptr<T>>\n{\n    static void to_json( nlohmann::json& j, const std::unique_ptr<T>& value )\n    {\n        if ( !value )\n        {\n            throw nlohmann::json::type_error::create( 302, \"type must not be null, but is\" );\n        }\n\n        j = *value;\n    }\n\n    static void from_json( const nlohmann::json& j, std::unique_ptr<T>& p )\n    {\n        if ( j.is_null() )\n        {\n            throw nlohmann::json::type_error::create( 302, \"type must not be null, but is\" );\n        }\n\n        p = std::make_unique<T>( j.get<T>() );\n    }\n};\n\ntemplate <typename T>\nstruct adl_serializer<std::shared_ptr<T>>\n{\n    static void to_json( nlohmann::json& j, const std::shared_ptr<T>& value )\n    {\n        if ( !value )\n        {\n            throw nlohmann::json::type_error::create( 302, \"type must not be null, but is\" );\n        }\n\n        j = *value;\n    }\n\n    static void from_json( const nlohmann::json& j, std::shared_ptr<T>& p )\n    {\n        if ( j.is_null() )\n        {\n            throw nlohmann::json::type_error::create( 302, \"type must not be null, but is\" );\n        }\n\n        p = std::make_shared<T>( j.get<T>() );\n    }\n};\n\ntemplate <typename T>\nstruct adl_serializer<std::optional<T>>\n{\n    static void to_json( nlohmann::json& j, const std::optional<T>& value )\n    {\n        if ( !value )\n        {\n            j = nlohmann::json();\n        }\n        else\n        {\n            j = *value;\n        }\n    }\n\n    static void from_json( const nlohmann::json& j, std::optional<T>& p )\n    {\n        if ( j.is_null() )\n        {\n            p = std::nullopt;\n        }\n        else\n        {\n            p = j.get<T>();\n        }\n    }\n};\n\ntemplate <>\nstruct adl_serializer<std::wstring>\n{\n    static void to_json( json& j, const std::wstring& value )\n    {\n        j = qwr::unicode::ToU8( value );\n    }\n\n    static void from_json( const json& j, std::wstring& value )\n    {\n        value = qwr::unicode::ToWide( j.get<std::string>() );\n    }\n};\n\n} // namespace nlohmann\n"
  },
  {
    "path": "foo_spotify/utils/rps_limiter.cpp",
    "content": "\n#include <stdafx.h>\n\n#include \"rps_limiter.h\"\n\n#include <backend/spotify_instance.h>\n#include <fb2k/advanced_config.h>\n#include <utils/abort_manager.h>\n#include <utils/sleeper.h>\n\n#include <qwr/final_action.h>\n\nnamespace\n{\n\nstd::chrono::milliseconds GetTimestampInMs()\n{\n    return std::chrono::time_point_cast<std::chrono::milliseconds>( std::chrono::system_clock::now() ).time_since_epoch();\n}\n\n} // namespace\n\nnamespace sptf\n{\n\nRpsLimiter::RpsLimiter( size_t limit, std::chrono::seconds limitPeriod )\n    : shouldLogWebApiDebug_( config::advanced::logging_webapi_debug )\n    , limitPeriod_( limitPeriod )\n    , limitCount_( limit )\n    , timeStampsContainer_( limit, GetTimestampInMs() - 2 * limitPeriod )\n    , timeStamps_( timeStampsContainer_.begin(), timeStampsContainer_.end(), timeStampsContainer_.begin(), timeStampsContainer_.size() )\n{\n}\n\nvoid RpsLimiter::WaitForRequestAvailability( abort_callback& abort )\n{\n    if ( abort.is_aborting() )\n    {\n        return;\n    }\n\n    std::atomic_bool timeToDie = false;\n    auto& am = SpotifyInstance::Get().GetAbortManager();\n    const auto abortableScope = am.GetAbortableScope( [&] {\n        timeToDie = true;\n        cv_.notify_all();\n    },\n                                                      abort );\n\n    std::unique_lock lock( mutex_ );\n\n    const auto nowInMs = GetTimestampInMs();\n    auto nextAvailableTime = timeStamps_.front() + limitPeriod_;\n    if ( incomingRequests_.empty() && nowInMs >= nextAvailableTime )\n    {\n        timeStamps_.emplace_back( nowInMs );\n        return;\n    }\n\n    auto waitTime = nextAvailableTime - nowInMs;\n\n    const auto requestIdx = curRequestIdx_++;\n    incomingRequests_.emplace_back( requestIdx );\n    const auto curIt = std::prev( incomingRequests_.end() );\n    const qwr::final_action autoEraseRequest( [&] {\n        incomingRequests_.erase( curIt );\n    } );\n\n    while ( true )\n    {\n        if ( shouldLogWebApiDebug_ )\n        {\n            FB2K_console_formatter() << SPTF_UNDERSCORE_NAME \" (debug):\\n\"\n                                     << fmt::format( \"throttling for {} milliseconds\", waitTime.count() );\n        }\n\n        bool hasEvent = cv_.wait_for( lock, waitTime, [&] {\n            return timeToDie || ( incomingRequests_.front() == requestIdx && GetTimestampInMs() >= nextAvailableTime );\n        } );\n\n        if ( hasEvent )\n        {\n            if ( !timeToDie )\n            {\n                timeStamps_.emplace_back( GetTimestampInMs() );\n            }\n            return;\n        }\n\n        nextAvailableTime = GetTimestampInMs() + limitPeriod_ / limitCount_;\n        waitTime = limitPeriod_ / limitCount_;\n    }\n}\n\n} // namespace sptf\n"
  },
  {
    "path": "foo_spotify/utils/rps_limiter.h",
    "content": "#pragma once\n\n#include <nonstd/ring_span.hpp>\n\n#include <chrono>\n#include <list>\n#include <mutex>\n#include <vector>\n\nnamespace sptf\n{\n\nclass RpsLimiter\n{\npublic:\n    RpsLimiter( size_t limit, std::chrono::seconds limitPeriod = std::chrono::seconds( 1 ) );\n    ~RpsLimiter() = default;\n\n    void WaitForRequestAvailability( abort_callback& abort );\n\nprivate:\n    const bool shouldLogWebApiDebug_;\n\n    const std::chrono::seconds limitPeriod_;\n    const size_t limitCount_;\n\n    std::mutex mutex_;\n    std::condition_variable cv_;\n\n    std::vector<std::chrono::milliseconds> timeStampsContainer_;\n    nonstd::ring_span<\n        std::chrono::milliseconds,\n        nonstd::null_popper<std::chrono::milliseconds>>\n        timeStamps_;\n\n    size_t curRequestIdx_ = 0;\n    // TODO: replace list with queue\n    std::list<size_t> incomingRequests_;\n};\n\n} // namespace sptf\n"
  },
  {
    "path": "foo_spotify/utils/secure_vector.h",
    "content": "#pragma once\n\n#include <vector>\n\nnamespace sptf\n{\n\ntemplate <class T>\nclass SecureAllocator\n{\npublic:\n    static_assert( !std::is_const<T>::value,\n                   \"The C++ Standard forbids containers of const elements \"\n                   \"because allocator<const T> is ill-formed.\" );\n\n    using value_type = T;\n    using propagate_on_container_move_assignment = std::true_type;\n    using is_always_equal = std::true_type;\n\n    constexpr SecureAllocator() noexcept\n    {\n    }\n\n    constexpr SecureAllocator( const SecureAllocator& ) noexcept = default;\n\n    template <class OtherT>\n    constexpr SecureAllocator( const SecureAllocator<OtherT>& ) noexcept\n    {\n    }\n\n    void deallocate( T* const ptr, const size_t count )\n    {\n        SecureZeroMemory( reinterpret_cast<uint8_t*>( ptr ), count * sizeof( T ) );\n        baseAllocator_.deallocate( ptr, count );\n    }\n\n    [[nodiscard]] T* allocate( const size_t count )\n    {\n        return baseAllocator_.allocate( count );\n    }\n\nprivate:\n    std::allocator<T> baseAllocator_;\n};\n\ntemplate <class T, class OtherT>\n[[nodiscard]] inline bool operator==( const SecureAllocator<T>&,\n                                      const SecureAllocator<OtherT>& ) noexcept\n{\n    return true;\n}\n\ntemplate <class T, class OtherT>\n[[nodiscard]] inline bool operator!=( const SecureAllocator<T>&,\n                                      const SecureAllocator<OtherT>& ) noexcept\n{\n    return false;\n}\n\ntemplate <class T>\nusing SecureVector = std::vector<T, SecureAllocator<T>>;\n\n} // namespace sptf\n"
  },
  {
    "path": "foo_spotify/utils/sleeper.cpp",
    "content": "#include <stdafx.h>\n\n#include \"sleeper.h\"\n\n#include <backend/spotify_instance.h>\n#include <utils/abort_manager.h>\n\n#include <condition_variable>\n#include <mutex>\n\nnamespace sptf\n{\n\nbool SleepFor( const std::chrono::milliseconds& duration, abort_callback& abort )\n{\n    std::mutex mtx;\n    std::condition_variable cv;\n    bool timeToDie = false;\n\n    auto& am = SpotifyInstance::Get().GetAbortManager();\n    auto abortableScope = am.GetAbortableScope( [&] {\n        {\n            std::lock_guard lock( mtx );\n            timeToDie = true;\n        }\n        cv.notify_all();\n    },\n                                                abort );\n\n    std::unique_lock lock( mtx );\n    return !cv.wait_for( lock, duration, [&] { return timeToDie; } );\n}\n\n} // namespace sptf\n"
  },
  {
    "path": "foo_spotify/utils/sleeper.h",
    "content": "#pragma once\n\n#include <chrono>\n\nnamespace sptf\n{\n\nbool SleepFor( const std::chrono::milliseconds& duration, abort_callback& abort );\n\n} // namespace sptf\n"
  },
  {
    "path": "libspotify/ChangeLog",
    "content": "Version 12\n\n\tAdded Android support.\n\n\tAdded functionality for controlling scrobbling.\n\n\tAdded function sp_session_user_name, suitable for using\n\tin conjunction with the credentials_blob_updated callback.\n\n\tAdded connectionstate_updated callback.\n\n\tAdded support for low- and high-res images.\n\n\tFixed a bug where libspotify would crash on reusing credentials\n\twhen password had been changed.\n\n\tFixed a bug where sp_search_total_playlists would always return 0.\n\n\tFixed apparently random crash on multi-core ARM devices.\n\n\tVarious bug fixes.\n\nVersion 11\n\n\tThe end_of_track() callback in session has changed and is now\n\tinvoked on the main thread. Depending on how your application\n\tuse this callback some change might be necessary.\n\n\tArtist browse when used in SP_ARTISTBROWSE_NO_TRACKS or\n\tSP_ARTISTBROWSE_NO_ALBUMS also includes a list of top tracks for the\n\tArtist.\n\n\tThe SP_ARTISTBROWSE_FULL mode has been deprecated and will be\n\tremoved in a future release.\n\n\tArtist browse have been improved with tophit tracks.\n\tSee sp_artistbrowse_tophit_track() and\n\tsp_artistbrowse_num_tophit_tracks()\n\n\tNew method sp_session_flush_caches().  This will make libspotify\n\twrite all data that is meant to be stored on disk to the disk\n\timmediately. Libspotify does this periodically by itself and also\n\ton logout. So under normal conditions this should never need to be\n\tused.\n\n\tRemoved support for Mac OS X - PowerPC.\n\n\tNew callback, credentials_blob_updated() has been added.\n\tThis callback will be invoked when a login blob has been received\n\tby the client. You can use this blob to relogin a user (via\n\tsp_session_login()) much like the remember_me argument.\n\tThe difference between remember_me and the blob callback is that\n\tthe blob callback allows multiple users to be relogged in by\n\thaving the application store a blob for each user.\n\tUseful if your application supports multiple users\n\n\tsp_track_get_playable() will return the track that would actually\n\tbe played if a track is \"linked\". Linked tracks are redirect\n\tfrom an unplayable track to a track on a different album (which is\n\tavailable in the currently logged in user's region)\n\tNormally, your application does not need to worry about this but\n\tthe function is here for completeness.\n\n\tThe radio has been removed. The reason for this is that the\n\tradio features have been redesigned in the Spotify backend.\n\n\tA new feature have been added that allows a user to see\n\tthe number of new tracks added on a subscribed playlist.\n\tsp_playlistcontainer_get_unseen_tracks() returns number of new\n\ttracks (and optionally the tracks themselves)\n\tsp_playlistcontainer_clear_unseen_tracks() can be used to clear\n\tthe unseen track counter.\n\tThis feature is not available in the desktop client yet.\n\nVersion 10\n\n\tsp_track_is_available() has been renamed to sp_track_get_availability()\n\tThis new function returns more detailed information about why a track\n\tis not streamable.\n\n\tAdd error code SP_ERROR_NETWORK_DISABLED\n\n\tAdd error code SP_ERROR_INVALID_DEVICE_ID\n\n\tAdd sp_track_offline_get_status() to return offline status of a track.\n\n\tAdd sp_track_is_placeholder() that indicates if a track is a\n\tplaceholder track. Placeholder tracks are used to store items in\n\tplaylists that are not tracks but rather than changing the entire\n\tAPI to support arbitrary items the sp_track object will act as a\n\tproxy object. The placeholder track object only contains the URI\n\tto the real object. IE. after having determined that a track\n\tis a placeholder track the API user should use\n\tsp_link_create_from_track() to get an URI to the real object\n\tand continue to resolve the object from there.\n\n\tModify sp_artistbrowse_create() to take a type argument.\n\tPrior to this release sp_artistbrowse_create() queried\n\tSpotify's backend servers for all tracks related to an artist\n\tand doing an artist browse. This consumes a lot of memory\n\ton the host and for various embedded platforms this could\n\tresult in a crash. This new version of sp_artistbrowse_create()\n\toffers a way to only query for the albums when using\n\t'SP_ARTISTBROWSE_NO_TRACKS' (this would typically\n\tresult in 95% less memory used) or just data about the artist\n\titself 'SP_ARTISTBROWSE_NO_ALBUMS'. As most user interfaces\n\tlist albums when browsing an artist 'SP_ARTISTBROWSE_NO_TRACKS'\n\tshould almost always be used.\n\n\tAdd support for controlling volume normalization.\n\tNote that volume normalization is not enabled on some targets.\n\tIn particular that includes all arm-targets and all target without\n\tfast floating point (where libspotify uses fixed point vorbis\n\tdecoder instead)\n\n\tA couple of functions ending with _backend_request_duration()\n\thas been added. These functions can be used when analyzing\n\tperformance in an application to see how much time is spent\n\ton waiting for a request to be served by the Spotify backend\n\n\tA new session callback offline_error has been added that\n\tis called if there is some general problems with offline\n\tsynchronization of tracks.\n\tlibspotifys social integration requires a HTTPS client.\n\tThis needs to be supplied by the application.\n\tFor an example of how to do this (using libcurl) see the\n\tspshell example (spshell.c)\n\nVersion 9\n\n\tSPOTIFY_API_VERSION is bumped to 9.\n\n\tPackage version numbers have changed.\n\n\tThe distributed package (and the is so versioning where\n\tapplicable) is now versioned like this:\n\n\tlibspotify-X.Y.Z\n\n\tX - Major version. Always same as SPOTIFY_API_VERSION.\n\t    libraries with different major versions are not ABI compatible\n\n\tY - Minor version.\n\t    Is 0 during development. 1 for the first public release, etc\n\n\tZ - Patch version. Incremented for each change of the codebase\n\n\tlibspotify can now remember user credentials.\n\tThis should be used to automatically login the user.\n\tThe application MUST NEVER store the user's password.\n\n        - A fourth parameter has been added to sp_session_login() that\n\twill tell libspotify to remember the login credentials in an\n\tencrypted form stored in the settings_location as specified when\n\tcreating the session.\n\n\t- To relogin a user, the application should invoke\n\tsp_session_relogin() instead of sp_session_login().  If no\n\tcredentials are stored, SP_ERROR_NO_CREDENTIALS will be returned\n\n\t- To clear stored credentials, use sp_session_forget_me()\n\n\t- To get username of currently stored credentials use\n\tsp_session_remembered_user()\n\n\n\tAdd sp_session_offline_time_left() that returns time left until\n\tthe user is required to reconnect to Spotify in order to\n\trevalidate the offline keys.\n\n\tThe logged in state has been updated to include\n\tSP_CONNECTION_STATE_OFFLINE, which indicates that the user is\n\tlogged in to the Spotify service in offline mode.\n\n\tThe SP_ERROR_RESOURCE_NOT_LOADED, which was only used by\n\tsp_session_player_load(), has been replaced with SP_ERROR_IS_LOADING\n\twhich means the same thing.\n\n\tThe documentation has been updated to fix a few minor errors.\n\n\tcallback connection_error() will no longer be invoked if the error\n\tparameter has value SP_ERROR_OK, as it isn't an error.\n\n\tsp_track_set_starred and sp_playlist_add_tracks got their list\n\targuments const property changed from (const**) to (*const*).\n\n\tsp_link_create_from_artist_portrait() renamed to\n\tsp_link_create_from_artistbrowse_portrait() which is more appropriate.\n\n\tIntroduced sp_artist_portrait() and\n\tsp_link_create_from_artist_portrait() to get one artist portrait\n\tfrom an artist object. This should be used to get artist portraits\n\twhen doing search and top list browse queries.\n\n\tIntroduced sp_build_id() - This could be useful to display\n\tsomewhere deep down in the user interface in case you (or Spotify)\n\twould like to know the exact version running.\n\nVersion 0.0.8\n\n\tSPOTIFY_API_VERSION is bumped to 8.\n\n\tAdded support for offline mode.\n\tUsers of libspotify can now request playlists to be offline\n\tsynchronized just as Spotify's desktop and mobile applications.\n\tFor example of how to do this, please see cmd_playlist_offline()\n\tin playlist.c in the spshell example.\n\n\tAdded sp_playlistcontainer_is_loaded() which can be used to\n\tcheck if a playlistcontainer is loaded. This value will be true\n\tafter the container_loaded() callback is invoked.\n\n\tAdded support for spotify:image: linktype. If your application\n\tneeds an abstract way to refer to coverarts, artist portraits, etc\n\tthis is what you should use.\n\n\tAdd sp_session_user_country() that returns the currently logged in\n\tusers registered country. This is the country that should be used\n\tto get toplists localized for the user.\n\n\tbugfix: LocalTrack URI handling (sp_link) was broken. This has now\n\tbeen fixed\n\n\tbufix: libspotify was unable to link on 10.4 and 10.5. This has\n\tnow been fixed\n\nVersion 0.0.7\n\n\tSPOTIFY_API_VERSION is bumped to 7.\n\n\tIMPORTANT BEHAVIOR CHANGE: Prior to 0.0.7 libspotify would remove\n\tall notification callbacks the user had registered on a playlist\n\tif the playlist was removed from the root container.  This caused\n\ta problem such that if a playlist was still visible in a user\n\tinterface and got removed from the root container no further\n\tupdates to the list would be visible. There is really no good\n\treason to have such behavior and therefore libspotify no longer\n\tremove the registered notifications. So to be compatible with\n\tlibspotify 0.0.7 and maintain the previous behavior an\n\tapplication MUST unregister the callbacks it has registered\n\twhen the sp_playlistcontainer_callbacks::playlist_removed\n\tnotification is invoked. All the examples shipped with\n\tlibspotify already do this so if you have followed them you\n\tshould be OK.\n\n\tfeature: libspotify is now available for ARMv5, ARMv6 and ARMv7 on\n\tLinux/glibc\n\n\tbugfix: In 0.0.6 sp_playlistcontainer_playlist_folder_name()\n\treturned a pointer to free'd memory as the folder names are\n\tinternally generated on the fly. Now the caller will have to\n\tprovide a buffer to store the string instead.\n\n\tbugfix: If sp_playlistcontainer_add_callbacks() was called before\n\tlogin had succeed libspotify would crash. This was a regression\n\tin 0.0.6\n\n\tbugfix: sp_session_publishedcontainer_for_user() did not\n\tinitialize the playlist subsystem internally in the lib resulting\n\tin a crash.  This could be circumvented by invoking another\n\tplaylist related API call before calling\n\tsp_session_publishedcontainer_for_user().\n\n\tbugfix: sp_session_publishedcontainer_for_user() has been removed\n\tin favor of sp_session_publishedcontainer_for_user_create() which\n\tcreates a new object that the caller own and thus needs to release\n\tusing sp_playlistcontainer_release(). In 0.0.6 the\n\tsp_session_publishedcontainer_for_user() function did not claim\n\ta reference for the container internally and thus the container\n\twould eventually be flushed by the playlist garbage collector\n\tresulting in a crash.\n\n\tAll functions that return errors now have documentation that\n\tdescribers the errors they can return.\n\n\tSP_ERROR_NO_CACHE and SP_ERROR_NO_SUCH_USER error codes have\n\tbeen added.\n\n\tInbox functionality now have support for messages attached to\n\teach track.\n\n\tAdd support for creating playlist folders. See notes in\n\tsp_playlistcontainer_add_folder() for how to delete and rename\n\tfolders.\n\n\tMake it possible to modify seen status of tracks in playlist.\n\tSee sp_playlist_track_set_seen()\n\n\tAdd support for playlist subscription information.\n\tSee sp_playlist_update_subscribers()\n\n\tThe 'tiny_settings' session configuration flag has been removed\n\tin favor of more granular flags. See documentation in\n\tsp_session_config for more details.\n\n\tAdd support for moving playlists out of RAM and store bulk\n\tof the information on disk. See sp_playlist_is_in_ram() documentation\n\tfor more details.\n\n\tThe spshell example did not initialize unused fields in\n\tsp_session_config to zero. This is good practice to avoid\n\taccidentally enabling features when compiling with a newer\n\tversion of the lib.\n\n\tPlaylist containers can now be properly reference counted.\n\tSee sp_playlistcontainer_add_ref() and\n\tsp_playlistcontainer_release().\n\n\n\n\n\nVersion 0.0.6\n\n\tSPOTIFY_API_VERSION is bumped to 6.\n\n\tfeature: Playlist folders. The folders are implemented as\n\tspecialized playlists. Two specialized types of playlists can be\n\tused to push/pop depth in the a playlist container view.  See\n\tsp_playlist_type and sp_playlistcontainer_playlist_type().\n\n\tfeature: Auto linking of tracks, see sp_track_is_autolinked().\n\n\tfeature: Add support for extracting playlist description and\n\tplaylist images.\n\n\tfeature: Make it possible to query if a track is a local track.\n\tSee sp_track_is_local().\n\n\tfeature: sp_session_release() is now available and thus,\n\tsp_session_init() has been renamed to sp_session_create()\n\n\tfeature: Improved audio delivery handling.\n\n\tAn application may choose to implement a callback in the session\n\tstruct that allows libspotify to query the application audio buffer\n\tstatistics.  The application should return number of samples\n\tcurrently in its buffer and also if it has experienced any audio\n\tdropouts (stutters) since the last query. The query\n\tcallback (get_audio_buffer_stats) will be invoked ca 10 times per\n\tsecond.\n\n\tIf an application implements the get_audio_buffer_stats() it may\n\talso choose to implement the start_playback() and stop_playback()\n\tcallbacks.  The start_playback() callback will be invoked when\n\tthere is enough samples in the buffer and the session player is in\n\tplay mode,see sp_session_player_play()\n\n\tThe stop_playback() callback will be invoked when playback is\n\tpaused and when a track ends.\n\n\tIf an application reports that it has experienced stutter it may\n\tput itself in paused state and wait for start_playback() to be\n\tinvoked. This will happen once libspotify is satisfied with the\n\tbuffer fullness.  No stop_playback() will be invoked in this case.\n\n\tfeature: Prefetching of tracks has been added. See\n\tsp_session_player_prefetch(). Note that prefetch only works if\n\tthe caching is enabled.\n\n\tfeature: A new session configuration variable 'tiny_settings' is\n\tavailable that, when set, tries to minimize the data store in the\n\tsettings dir as much as possible without affecting the user\n\texperience too much. Set this if free disk space is precious.\n\n\nVersion 0.0.5\n\n\tSPOTIFY_API_VERSION is bumped to 5.\n\n\tfeature: The cache size can now be explicitly configured.  See\n\tsp_session_set_cache_size().\n\n\tfeature: Support for getting create user and time for playlist entries.\n\tSee sp_playlist_track_creator() sp_playlist_track_create_time() and the\n\ttrack_created_changed callback.\n\n\tfeature: Support for loading currently logged in user's Inbox.  See\n\tsp_session_inbox(), sp_playlist_track_seen() and the track_seen_changed\n\tplaylist callback.\n\n\tfeature: Three new link types SP_LINKTYPE_PROFILE,\n\tSP_LINKTYPE_STARRED and SP_LINKTYPE_LOCALTRACK\n\n\tfeature: Support for browsing other users toplists. See\n\tsp_toplistbrowse_create().\n\n\tfeature: Support for browsing published lists. See\n\tsp_session_publishedcontainer_for_user() and\n\tsp_session_publishedcontainer_for_user_release(), also you can\n\tget the user object for a playlistcontainer using\n\tsp_playlistcontainer_owner.\n\n\tfeature: Support creating local tracks. See sp_localtrack_create().\n\n\tABI change: sp_track_is_available() & sp_track_is_starred() now need\n\tsp_session to be passed as an argument.\n\nVersion 0.0.4\n\n\tSPOTIFY_API_VERSION is bumped to 4.\n\n\tfeature: libspotify is now available for Win32 and OS/X platforms.\n\n\tfeature: Add support for starred tracks. See sp_track_is_starred(),\n\tsp_track_set_starred() and sp_session_starred_create().\n\n\tfeature: Add support for radio. See sp_radio_search_create().\n\n\tfeature: Add support for loading playlist without adding them to\n\tthe users's playlist container. See sp_playlist_create().\n\n\tfeature: Add support for 320kb/s streaming. See\n\tsp_session_preferred_bitrate().\n\n\tfeature: Added new session callback streaming_error() that is invoked\n\tif the library is unable to play the requested track.\n\n\tfeature: Add new session callback userinfo_updated() that is invoked\n\twhen one or more sp_user entries have been updated.\n\n\tABI change: Due to internal changes, the sp_playlist_add_tracks()\n\tneeds sp_session to be passed as an argument.\n\n\tAPI change: The include file has been renamed from spotify/api.h to\n\tlibspotify/api.h for coherency reasons.\n\nVersion 0.0.3\n\n\tSPOTIFY_API_VERSION is bumped to 3.\n\n\tfeature: libspotify is now available for 64-bit x86 Linux platforms\n\n\tfeature: sp_artistbrowse_num_albums() and sp_artistbrowse_album()\n\thave been added so users of the API can list all albums returned\n\tin an artist browse.\n\n\tbugfix: SP_ERROR_OTHER_PERMAMENT renamed to SP_ERROR_OTHER_PERMANENT\n\n\tfeature: The sp_image API has changed. libspotify now exposes the\n\tsource image data via the API. See sp_image_data() and\n\tsp_image_format()\n\n\tfeature: Playlistcontainer have a new callback container_loaded()\n\tthat is invoked after the container has been initially\n\tsynchronized from the server.\n\n\tfeature: Added support for toplists. See the sp_toplistbrowse API\n\tfunctions.\n\n\tfeature: Add sp_link_as_track_and_offset() for getting play start\n\toffset encoded in URIs.\n\nVersion 0.0.2\n\n\tSPOTIFY_API_VERSION is bumped to 2.\n\n\tfeature: sp_search_create() has been extended with offset and\n\tlimit for album and artist results.\n\n\tbugfix: libspotify contained a bug that caused it to hang if a\n\tplaylist was removed when libspotify was running.\n\n\tfeature: sp_track_is_available() has been added to allow the user\n\tto query if a track can be played or not due to regional\n\trestrictions.\n\n\tfeature: sp_album_is_available() has been added to allow the user\n\tto query if a album is available or not due to regional\n\trestrictions.\n\n\tfeature: playlist_metadata_updated() per-playlist callback has\n\tbeen added, allowing the user to refresh metadata for tracks in a\n\tplaylist.\n\n\tfeature: sp_album_type() has been added to allow the user to find\n\tout the album type. See the sp_albumtype enum for the available\n\ttypes.\n\n\tfeature: An end_of_track() session callback has been added. Prior\n\tto this release the music_delivery() callback would be invoked\n\twith num_frames set to 0 both to indicate audio discontinuity (as\n\ta result of a seek from the main thread) and also to indicate\n\tend-of-track.  To ease application development, end_of_track() is\n\tnow invoked at the end of a track and music_delivery() is only\n\tinvoked with num_frames set to 0 as a result of a seek.\n\n\nVersion 0.0.1\n\n\tInitial release\n"
  },
  {
    "path": "libspotify/LICENSE",
    "content": "For the current terms and conditions, please read:\n\nhttp://developer.spotify.com/en/libspotify/terms-of-use/\n"
  },
  {
    "path": "libspotify/README",
    "content": "\n                                 libspotify 12.1.51\n                   ----------------------------------------\n\n                       Copyright  2006-2012 Spotify Ltd\n\n\n\n1.  INTRODUCTION\n\n    This is the libspotify C API package.  With it, you can write applications\n    that utilize the Spotify music streaming service.\n\n\n2.  PACKAGE STRUCTURE\n\n    The package is structured as follows:\n\n      libspotify\\\n        README.txt                     This README file\n        LICENSE.txt                    License governing the library,\n                                       and associated files\n        ChangeLog.txt                  Contains description of new and changed\n                                       functionality in libspotify\n        licenses.xhtml                 License governing third party libraries\n                                       included in libspotify.\n        include\\libspotify\\api.h       Header file for the library\n        lib\\\n          libspotify.dll               libspotify DLL file\n          libspotify.lib               Import library\n        doc\\\n          html\\                        Documentation in HTML format\n                                       This information is also available online.\n          images\\                      Graphics for use with applications\n                                       using libspotify. See section 6 below.\n        examples\\                      Root directory for the example\n                                       source code\n\n3.  INSTALLATION\n\n    You have probably unpacked the distribution zip archive already.\n\n    To run the compiled examples you need to include the directory\n    where libspotify.dll resides in your system PATH environment\n    variable. For more details see this MSDN article about Windows DLL\n    search paths:\n\n    http://msdn.microsoft.com/en-us/library/7d83bc18.aspx\n    \n\n4.  APPLICATION KEYS\n\n    The example programs require a file called appkey.c which is not present in\n    the package.  You will need to request an application key at the\n    developer website at http://developer.spotify.com/ before being able to\n    run them.\n\n\n5.  LOGOTYPES AND TRADEMARK\n\n    The graphics found in the images/ subdirectory are available for use in\n    applications using libspotify. The terms and conditions for the use of these\n    are available on http://developer.spotify.com/.\n\n    A text file is included in images/, containing the text to be used in\n    non-graphical applications.\n\n\n6.  LICENSE\n\n    You should have received a separate LICENSE file together with this README.\n"
  },
  {
    "path": "libspotify/docs/html/annotated.html",
    "content": "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\n<html xmlns=\"http://www.w3.org/1999/xhtml\">\n<head>\n<meta http-equiv=\"Content-Type\" content=\"text/xhtml;charset=UTF-8\"/>\n<title>libspotify: Data Structures</title>\n<link href=\"tabs.css\" rel=\"stylesheet\" type=\"text/css\"/>\n<link href=\"doxygen.css\" rel=\"stylesheet\" type=\"text/css\"/>\n</head>\n<body>\n<!-- Generated by Doxygen 1.7.1 -->\n<div class=\"navigation\" id=\"top\">\n  <div class=\"tabs\">\n    <ul class=\"tablist\">\n      <li><a href=\"index.html\"><span>Main&nbsp;Page</span></a></li>\n      <li><a href=\"modules.html\"><span>Modules</span></a></li>\n      <li class=\"current\"><a href=\"annotated.html\"><span>Data&nbsp;Structures</span></a></li>\n      <li><a href=\"files.html\"><span>Files</span></a></li>\n      <li><a href=\"examples.html\"><span>Examples</span></a></li>\n    </ul>\n  </div>\n  <div class=\"tabs2\">\n    <ul class=\"tablist\">\n      <li class=\"current\"><a href=\"annotated.html\"><span>Data&nbsp;Structures</span></a></li>\n      <li><a href=\"functions.html\"><span>Data&nbsp;Fields</span></a></li>\n    </ul>\n  </div>\n</div>\n<div class=\"header\">\n  <div class=\"headertitle\">\n<h1>Data Structures</h1>  </div>\n</div>\n<div class=\"contents\">\nHere are the data structures with brief descriptions:<table>\n  <tr><td class=\"indexkey\"><a class=\"el\" href=\"structsp__audio__buffer__stats.html\">sp_audio_buffer_stats</a></td><td class=\"indexvalue\"></td></tr>\n  <tr><td class=\"indexkey\"><a class=\"el\" href=\"structsp__audioformat.html\">sp_audioformat</a></td><td class=\"indexvalue\"></td></tr>\n  <tr><td class=\"indexkey\"><a class=\"el\" href=\"structsp__offline__sync__status.html\">sp_offline_sync_status</a></td><td class=\"indexvalue\"></td></tr>\n  <tr><td class=\"indexkey\"><a class=\"el\" href=\"structsp__playlist__callbacks.html\">sp_playlist_callbacks</a></td><td class=\"indexvalue\"></td></tr>\n  <tr><td class=\"indexkey\"><a class=\"el\" href=\"structsp__playlistcontainer__callbacks.html\">sp_playlistcontainer_callbacks</a></td><td class=\"indexvalue\"></td></tr>\n  <tr><td class=\"indexkey\"><a class=\"el\" href=\"structsp__session__callbacks.html\">sp_session_callbacks</a></td><td class=\"indexvalue\"></td></tr>\n  <tr><td class=\"indexkey\"><a class=\"el\" href=\"structsp__session__config.html\">sp_session_config</a></td><td class=\"indexvalue\"></td></tr>\n  <tr><td class=\"indexkey\"><a class=\"el\" href=\"structsp__subscribers.html\">sp_subscribers</a></td><td class=\"indexvalue\"></td></tr>\n</table>\n</div>\n<hr size=\"1\"><address style=\"text-align: right;\"><small>\nGenerated on Wed Jun 13 2012 14:22:40.<br>\nCopyright &copy; 2006&ndash;2012 Spotify Ltd</small></address>\n</body>\n</html>\n"
  },
  {
    "path": "libspotify/docs/html/api_8h.html",
    "content": "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\n<html xmlns=\"http://www.w3.org/1999/xhtml\">\n<head>\n<meta http-equiv=\"Content-Type\" content=\"text/xhtml;charset=UTF-8\"/>\n<title>libspotify: api.h File Reference</title>\n<link href=\"tabs.css\" rel=\"stylesheet\" type=\"text/css\"/>\n<link href=\"doxygen.css\" rel=\"stylesheet\" type=\"text/css\"/>\n</head>\n<body>\n<!-- Generated by Doxygen 1.7.1 -->\n<div class=\"navigation\" id=\"top\">\n  <div class=\"tabs\">\n    <ul class=\"tablist\">\n      <li><a href=\"index.html\"><span>Main&nbsp;Page</span></a></li>\n      <li><a href=\"modules.html\"><span>Modules</span></a></li>\n      <li><a href=\"annotated.html\"><span>Data&nbsp;Structures</span></a></li>\n      <li class=\"current\"><a href=\"files.html\"><span>Files</span></a></li>\n      <li><a href=\"examples.html\"><span>Examples</span></a></li>\n    </ul>\n  </div>\n  <div class=\"tabs2\">\n    <ul class=\"tablist\">\n      <li><a href=\"files.html\"><span>File&nbsp;List</span></a></li>\n      <li><a href=\"globals.html\"><span>Globals</span></a></li>\n    </ul>\n  </div>\n</div>\n<div class=\"header\">\n  <div class=\"summary\">\n<a href=\"#nested-classes\">Data Structures</a> &#124;\n<a href=\"#define-members\">Defines</a> &#124;\n<a href=\"#typedef-members\">Typedefs</a> &#124;\n<a href=\"#enum-members\">Enumerations</a> &#124;\n<a href=\"#func-members\">Functions</a>  </div>\n  <div class=\"headertitle\">\n<h1>api.h File Reference</h1>  </div>\n</div>\n<div class=\"contents\">\n<code>#include &lt;stddef.h&gt;</code><br/>\n<code>#include &lt;stdint.h&gt;</code><br/>\n<table class=\"memberdecls\">\n<tr><td colspan=\"2\"><h2><a name=\"nested-classes\"></a>\nData Structures</h2></td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">struct &nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"structsp__audioformat.html\">sp_audioformat</a></td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">struct &nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"structsp__audio__buffer__stats.html\">sp_audio_buffer_stats</a></td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">struct &nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"structsp__subscribers.html\">sp_subscribers</a></td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">struct &nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"structsp__offline__sync__status.html\">sp_offline_sync_status</a></td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">struct &nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"structsp__session__callbacks.html\">sp_session_callbacks</a></td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">struct &nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"structsp__session__config.html\">sp_session_config</a></td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">struct &nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"structsp__playlist__callbacks.html\">sp_playlist_callbacks</a></td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">struct &nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"structsp__playlistcontainer__callbacks.html\">sp_playlistcontainer_callbacks</a></td></tr>\n<tr><td colspan=\"2\"><h2><a name=\"define-members\"></a>\nDefines</h2></td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">#define&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__session.html#ga63b2309874193750ec3395f6cae32899\">SPOTIFY_API_VERSION</a>&nbsp;&nbsp;&nbsp;12</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">#define&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__toplist.html#gaa078b44491f976af43e4941fd1dd032c\">SP_TOPLIST_REGION</a>(a, b)&nbsp;&nbsp;&nbsp;((a) &lt;&lt; 8 | (b))</td></tr>\n<tr><td colspan=\"2\"><h2><a name=\"typedef-members\"></a>\nTypedefs</h2></td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"anchor\" id=\"ga70dd19c6f824cf6a159575aa4c128b53\"></a><!-- doxytag: member=\"api.h::sp_session\" ref=\"ga70dd19c6f824cf6a159575aa4c128b53\" args=\"\" -->\ntypedef struct <a class=\"el\" href=\"group__types.html#ga70dd19c6f824cf6a159575aa4c128b53\">sp_session</a>&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__types.html#ga70dd19c6f824cf6a159575aa4c128b53\">sp_session</a></td></tr>\n<tr><td class=\"mdescLeft\">&nbsp;</td><td class=\"mdescRight\">Representation of a session. <br/></td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"anchor\" id=\"ga47bbd2262f0c8b5d7147af7d62198e48\"></a><!-- doxytag: member=\"api.h::sp_track\" ref=\"ga47bbd2262f0c8b5d7147af7d62198e48\" args=\"\" -->\ntypedef struct <a class=\"el\" href=\"group__types.html#ga47bbd2262f0c8b5d7147af7d62198e48\">sp_track</a>&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__types.html#ga47bbd2262f0c8b5d7147af7d62198e48\">sp_track</a></td></tr>\n<tr><td class=\"mdescLeft\">&nbsp;</td><td class=\"mdescRight\">A track handle. <br/></td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"anchor\" id=\"ga6fd3e5de729c429fef3ff18ece6dcfad\"></a><!-- doxytag: member=\"api.h::sp_album\" ref=\"ga6fd3e5de729c429fef3ff18ece6dcfad\" args=\"\" -->\ntypedef struct <a class=\"el\" href=\"group__types.html#ga6fd3e5de729c429fef3ff18ece6dcfad\">sp_album</a>&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__types.html#ga6fd3e5de729c429fef3ff18ece6dcfad\">sp_album</a></td></tr>\n<tr><td class=\"mdescLeft\">&nbsp;</td><td class=\"mdescRight\">An album handle. <br/></td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"anchor\" id=\"ga31764fbd69618c10be173c6c03d4c1bc\"></a><!-- doxytag: member=\"api.h::sp_artist\" ref=\"ga31764fbd69618c10be173c6c03d4c1bc\" args=\"\" -->\ntypedef struct <a class=\"el\" href=\"group__types.html#ga31764fbd69618c10be173c6c03d4c1bc\">sp_artist</a>&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__types.html#ga31764fbd69618c10be173c6c03d4c1bc\">sp_artist</a></td></tr>\n<tr><td class=\"mdescLeft\">&nbsp;</td><td class=\"mdescRight\">An artist handle. <br/></td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"anchor\" id=\"gafd3d5aae485f1012ec91b7948e6f9f2b\"></a><!-- doxytag: member=\"api.h::sp_artistbrowse\" ref=\"gafd3d5aae485f1012ec91b7948e6f9f2b\" args=\"\" -->\ntypedef struct <a class=\"el\" href=\"group__types.html#gafd3d5aae485f1012ec91b7948e6f9f2b\">sp_artistbrowse</a>&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__types.html#gafd3d5aae485f1012ec91b7948e6f9f2b\">sp_artistbrowse</a></td></tr>\n<tr><td class=\"mdescLeft\">&nbsp;</td><td class=\"mdescRight\">A handle to an artist browse result. <br/></td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"anchor\" id=\"ga9c4550473a7a07790778ba870c31b4d9\"></a><!-- doxytag: member=\"api.h::sp_albumbrowse\" ref=\"ga9c4550473a7a07790778ba870c31b4d9\" args=\"\" -->\ntypedef struct <a class=\"el\" href=\"group__types.html#ga9c4550473a7a07790778ba870c31b4d9\">sp_albumbrowse</a>&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__types.html#ga9c4550473a7a07790778ba870c31b4d9\">sp_albumbrowse</a></td></tr>\n<tr><td class=\"mdescLeft\">&nbsp;</td><td class=\"mdescRight\">A handle to an album browse result. <br/></td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"anchor\" id=\"ga723de429cd073bcf5d13fb4e0f466ffd\"></a><!-- doxytag: member=\"api.h::sp_toplistbrowse\" ref=\"ga723de429cd073bcf5d13fb4e0f466ffd\" args=\"\" -->\ntypedef struct <a class=\"el\" href=\"group__types.html#ga723de429cd073bcf5d13fb4e0f466ffd\">sp_toplistbrowse</a>&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__types.html#ga723de429cd073bcf5d13fb4e0f466ffd\">sp_toplistbrowse</a></td></tr>\n<tr><td class=\"mdescLeft\">&nbsp;</td><td class=\"mdescRight\">A handle to a toplist browse result. <br/></td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"anchor\" id=\"gac95893a6b23d4b19f6f149eed6ead1fd\"></a><!-- doxytag: member=\"api.h::sp_search\" ref=\"gac95893a6b23d4b19f6f149eed6ead1fd\" args=\"\" -->\ntypedef struct <a class=\"el\" href=\"group__types.html#gac95893a6b23d4b19f6f149eed6ead1fd\">sp_search</a>&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__types.html#gac95893a6b23d4b19f6f149eed6ead1fd\">sp_search</a></td></tr>\n<tr><td class=\"mdescLeft\">&nbsp;</td><td class=\"mdescRight\">A handle to a search result. <br/></td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"anchor\" id=\"gaf90a23d6b662c96d52ac19f7f4bc1e39\"></a><!-- doxytag: member=\"api.h::sp_link\" ref=\"gaf90a23d6b662c96d52ac19f7f4bc1e39\" args=\"\" -->\ntypedef struct <a class=\"el\" href=\"group__types.html#gaf90a23d6b662c96d52ac19f7f4bc1e39\">sp_link</a>&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__types.html#gaf90a23d6b662c96d52ac19f7f4bc1e39\">sp_link</a></td></tr>\n<tr><td class=\"mdescLeft\">&nbsp;</td><td class=\"mdescRight\">A handle to the libspotify internal representation of a URI. <br/></td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"anchor\" id=\"ga61155ca7b1ba941e15490e417441917b\"></a><!-- doxytag: member=\"api.h::sp_image\" ref=\"ga61155ca7b1ba941e15490e417441917b\" args=\"\" -->\ntypedef struct <a class=\"el\" href=\"group__types.html#ga61155ca7b1ba941e15490e417441917b\">sp_image</a>&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__types.html#ga61155ca7b1ba941e15490e417441917b\">sp_image</a></td></tr>\n<tr><td class=\"mdescLeft\">&nbsp;</td><td class=\"mdescRight\">A handle to an image. <br/></td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"anchor\" id=\"gaed2dbaa1eebd6752f76613daad9158bc\"></a><!-- doxytag: member=\"api.h::sp_user\" ref=\"gaed2dbaa1eebd6752f76613daad9158bc\" args=\"\" -->\ntypedef struct <a class=\"el\" href=\"group__types.html#gaed2dbaa1eebd6752f76613daad9158bc\">sp_user</a>&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__types.html#gaed2dbaa1eebd6752f76613daad9158bc\">sp_user</a></td></tr>\n<tr><td class=\"mdescLeft\">&nbsp;</td><td class=\"mdescRight\">A handle to a user. <br/></td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"anchor\" id=\"ga1bcf54cbc117a20ab2c15e59eb3a8174\"></a><!-- doxytag: member=\"api.h::sp_playlist\" ref=\"ga1bcf54cbc117a20ab2c15e59eb3a8174\" args=\"\" -->\ntypedef struct <a class=\"el\" href=\"group__types.html#ga1bcf54cbc117a20ab2c15e59eb3a8174\">sp_playlist</a>&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__types.html#ga1bcf54cbc117a20ab2c15e59eb3a8174\">sp_playlist</a></td></tr>\n<tr><td class=\"mdescLeft\">&nbsp;</td><td class=\"mdescRight\">A playlist handle. <br/></td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"anchor\" id=\"ga45a2febbe167483e48dab8d606d462d7\"></a><!-- doxytag: member=\"api.h::sp_playlistcontainer\" ref=\"ga45a2febbe167483e48dab8d606d462d7\" args=\"\" -->\ntypedef struct <a class=\"el\" href=\"group__types.html#ga45a2febbe167483e48dab8d606d462d7\">sp_playlistcontainer</a>&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__types.html#ga45a2febbe167483e48dab8d606d462d7\">sp_playlistcontainer</a></td></tr>\n<tr><td class=\"mdescLeft\">&nbsp;</td><td class=\"mdescRight\">A playlist container (playlist containing other playlists) handle. <br/></td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"anchor\" id=\"gaec0f2e5098cebc05ce56adfc9b346510\"></a><!-- doxytag: member=\"api.h::sp_inbox\" ref=\"gaec0f2e5098cebc05ce56adfc9b346510\" args=\"\" -->\ntypedef struct <a class=\"el\" href=\"group__types.html#gaec0f2e5098cebc05ce56adfc9b346510\">sp_inbox</a>&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__types.html#gaec0f2e5098cebc05ce56adfc9b346510\">sp_inbox</a></td></tr>\n<tr><td class=\"mdescLeft\">&nbsp;</td><td class=\"mdescRight\">Add to inbox request handle. <br/></td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">typedef enum <a class=\"el\" href=\"group__error.html#gafd27986ce4cd9eeaeca8adda83c9eb6b\">sp_error</a>&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__error.html#ga83154178d3a32668658734d2facfa22b\">sp_error</a></td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">typedef enum <a class=\"el\" href=\"group__session.html#gabf77bb5a124d5a6ee9a12c86abbc0d34\">sp_connectionstate</a>&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__session.html#gac0fa3d4cc60bd2e3d666026f88980e8c\">sp_connectionstate</a></td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">typedef enum <a class=\"el\" href=\"group__session.html#ga087d21080010768316cfb55d938eb94d\">sp_sampletype</a>&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__session.html#ga5ef462e78d5a5af60dd0e7085b1ba512\">sp_sampletype</a></td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">typedef struct <a class=\"el\" href=\"structsp__audioformat.html\">sp_audioformat</a>&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__session.html#ga5338d4a10576ba8d6ab11b70892d503c\">sp_audioformat</a></td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">typedef enum <a class=\"el\" href=\"group__session.html#ga77ddd919314a7bb16140569af7a38fe2\">sp_bitrate</a>&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__session.html#ga83d3de45241a44e787410993c5fac0ea\">sp_bitrate</a></td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">typedef enum <a class=\"el\" href=\"group__session.html#gafdd7117213605e6f2671c4f289b44609\">sp_playlist_type</a>&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__session.html#ga86723f553db2db6a8f507cd748948ad4\">sp_playlist_type</a></td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">typedef enum <a class=\"el\" href=\"group__session.html#ga99e8e9176ce40fff08a9be8b944edb09\">sp_search_type</a>&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__session.html#ga647e4de81e5ac0a2e5d1193b1005ed3e\">sp_search_type</a></td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">typedef enum <br class=\"typebreak\"/>\n<a class=\"el\" href=\"group__session.html#ga811fa52ed0fdb5cda732682e27e40417\">sp_playlist_offline_status</a>&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__session.html#gac507efa32e8c122fbe9ea41d96180d06\">sp_playlist_offline_status</a></td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">typedef enum <a class=\"el\" href=\"group__session.html#gad7d9465769597b2a379ac704099adfdf\">sp_availability</a>&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__session.html#ga60c7ff53ddbc04c036a23181b7275d69\">sp_track_availability</a></td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">typedef enum <br class=\"typebreak\"/>\n<a class=\"el\" href=\"group__session.html#gaeaa41aad3c0047409996a6ec3b03203f\">sp_track_offline_status</a>&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__session.html#gae689044941537050de641a1dcd4c75d5\">sp_track_offline_status</a></td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">typedef enum <a class=\"el\" href=\"group__session.html#ga61bc424465d776af3ceeb69eee2bb492\">sp_image_size</a>&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__session.html#gaca320fd41bd0556b7fa1f2fa6e14faee\">sp_image_size</a></td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">typedef struct <br class=\"typebreak\"/>\n<a class=\"el\" href=\"structsp__audio__buffer__stats.html\">sp_audio_buffer_stats</a>&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__session.html#ga25462859a596a247ba5cc1853fc32cca\">sp_audio_buffer_stats</a></td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">typedef struct <a class=\"el\" href=\"structsp__subscribers.html\">sp_subscribers</a>&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__session.html#gafb515e30d134c61b8eaaff3177af0b5b\">sp_subscribers</a></td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">typedef enum <a class=\"el\" href=\"group__session.html#ga3e8773baeb94189b9a1ff27d6a5e3553\">sp_connection_type</a>&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__session.html#ga05a7dbb946a9c47bf011f3f3d77964c3\">sp_connection_type</a></td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">typedef enum <a class=\"el\" href=\"group__session.html#gad275d696685b2ad9ff1a2c3e16af6502\">sp_connection_rules</a>&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__session.html#ga24ee483cdceef9af3b415c020b197a75\">sp_connection_rules</a></td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">typedef enum <a class=\"el\" href=\"group__session.html#gac86504cc9e8cadbc30c8aa8dbf355034\">sp_artistbrowse_type</a>&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__session.html#gab947eba77c176504c69cbb2f1de9830d\">sp_artistbrowse_type</a></td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">typedef struct <br class=\"typebreak\"/>\n<a class=\"el\" href=\"structsp__offline__sync__status.html\">sp_offline_sync_status</a>&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__session.html#gaa7f24f13d6d105869c405045a4cc2a20\">sp_offline_sync_status</a></td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">typedef struct <a class=\"el\" href=\"structsp__session__callbacks.html\">sp_session_callbacks</a>&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__session.html#gaf1d92302cd5d0d4a032e1408188c8fd5\">sp_session_callbacks</a></td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">typedef struct <a class=\"el\" href=\"structsp__session__config.html\">sp_session_config</a>&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__session.html#ga372b25a93da38d4d707b0c2eaa7b3ebb\">sp_session_config</a></td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">typedef void&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__albumbrowse.html#gabd76254f89048e6d368929015a0c739f\">albumbrowse_complete_cb</a> (<a class=\"el\" href=\"group__types.html#ga9c4550473a7a07790778ba870c31b4d9\">sp_albumbrowse</a> *result, void *userdata)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">typedef void&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__artistbrowse.html#ga8077aa18c043210e859479be2616a3e7\">artistbrowse_complete_cb</a> (<a class=\"el\" href=\"group__types.html#gafd3d5aae485f1012ec91b7948e6f9f2b\">sp_artistbrowse</a> *result, void *userdata)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">typedef void&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__image.html#ga713bef7c5dedba7d91b9710cd9b5faa4\">image_loaded_cb</a> (<a class=\"el\" href=\"group__types.html#ga61155ca7b1ba941e15490e417441917b\">sp_image</a> *image, void *userdata)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">typedef void&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__search.html#gabcd51c99a318b9f36dfe2948d8209bb1\">search_complete_cb</a> (<a class=\"el\" href=\"group__types.html#gac95893a6b23d4b19f6f149eed6ead1fd\">sp_search</a> *result, void *userdata)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">typedef struct <br class=\"typebreak\"/>\n<a class=\"el\" href=\"structsp__playlist__callbacks.html\">sp_playlist_callbacks</a>&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__playlist.html#ga8249fe3d53c6dce0f154d0bfd3e80c6a\">sp_playlist_callbacks</a></td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">typedef struct <br class=\"typebreak\"/>\n<a class=\"el\" href=\"structsp__playlistcontainer__callbacks.html\">sp_playlistcontainer_callbacks</a>&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__playlist.html#ga8786e3840bb3774fc929183e3a9df281\">sp_playlistcontainer_callbacks</a></td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">typedef enum <a class=\"el\" href=\"group__user.html#ga6af84143c0622b6fc5539bb1ae111e5b\">sp_relation_type</a>&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__user.html#ga3a5dbf9aee629d8a9b43dfb24881a9b4\">sp_relation_type</a></td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">typedef void&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__toplist.html#gafe8e94ae23133105f35c03b9e3836a0a\">toplistbrowse_complete_cb</a> (<a class=\"el\" href=\"group__types.html#ga723de429cd073bcf5d13fb4e0f466ffd\">sp_toplistbrowse</a> *result, void *userdata)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">typedef void&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__inbox.html#ga5084d6ab753294730402a0c43b82e60c\">inboxpost_complete_cb</a> (<a class=\"el\" href=\"group__types.html#gaec0f2e5098cebc05ce56adfc9b346510\">sp_inbox</a> *result, void *userdata)</td></tr>\n<tr><td colspan=\"2\"><h2><a name=\"enum-members\"></a>\nEnumerations</h2></td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">enum &nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__error.html#gafd27986ce4cd9eeaeca8adda83c9eb6b\">sp_error</a> { <br/>\n&nbsp;&nbsp;<a class=\"el\" href=\"group__error.html#ggafd27986ce4cd9eeaeca8adda83c9eb6ba16cb277dc84328e4b2c0cf6d5a0c0b8d\">SP_ERROR_OK</a> =  0, \n<br/>\n&nbsp;&nbsp;<a class=\"el\" href=\"group__error.html#ggafd27986ce4cd9eeaeca8adda83c9eb6ba17c588fa9648e3649185e595bdb88d6f\">SP_ERROR_BAD_API_VERSION</a> =  1, \n<br/>\n&nbsp;&nbsp;<a class=\"el\" href=\"group__error.html#ggafd27986ce4cd9eeaeca8adda83c9eb6bac8c438bd52975d14edf23d040e93d114\">SP_ERROR_API_INITIALIZATION_FAILED</a> =  2, \n<br/>\n&nbsp;&nbsp;<a class=\"el\" href=\"group__error.html#ggafd27986ce4cd9eeaeca8adda83c9eb6ba7b94fe2b53f58d91d4c3cda7bb706ff3\">SP_ERROR_TRACK_NOT_PLAYABLE</a> =  3, \n<br/>\n&nbsp;&nbsp;<a class=\"el\" href=\"group__error.html#ggafd27986ce4cd9eeaeca8adda83c9eb6ba2bad808a467ee4418adaa40f4844d059\">SP_ERROR_BAD_APPLICATION_KEY</a> =  5, \n<br/>\n&nbsp;&nbsp;<a class=\"el\" href=\"group__error.html#ggafd27986ce4cd9eeaeca8adda83c9eb6ba41052a4a158fa18bb1b8bfdd8c37f7dc\">SP_ERROR_BAD_USERNAME_OR_PASSWORD</a> =  6, \n<br/>\n&nbsp;&nbsp;<a class=\"el\" href=\"group__error.html#ggafd27986ce4cd9eeaeca8adda83c9eb6ba822f4031a82ab428cd04f2ecdc0e757f\">SP_ERROR_USER_BANNED</a> =  7, \n<br/>\n&nbsp;&nbsp;<a class=\"el\" href=\"group__error.html#ggafd27986ce4cd9eeaeca8adda83c9eb6ba9d11d66176b6ae95bf00486e9e39866b\">SP_ERROR_UNABLE_TO_CONTACT_SERVER</a> =  8, \n<br/>\n&nbsp;&nbsp;<a class=\"el\" href=\"group__error.html#ggafd27986ce4cd9eeaeca8adda83c9eb6ba995344026c012b3f59dc73e12c28b1ba\">SP_ERROR_CLIENT_TOO_OLD</a> =  9, \n<br/>\n&nbsp;&nbsp;<a class=\"el\" href=\"group__error.html#ggafd27986ce4cd9eeaeca8adda83c9eb6ba3f68775a5c001bd1de26afdf5ea4e09d\">SP_ERROR_OTHER_PERMANENT</a> =  10, \n<br/>\n&nbsp;&nbsp;<a class=\"el\" href=\"group__error.html#ggafd27986ce4cd9eeaeca8adda83c9eb6baf3597d4af35adb4fc0d0793ea26f77b4\">SP_ERROR_BAD_USER_AGENT</a> =  11, \n<br/>\n&nbsp;&nbsp;<a class=\"el\" href=\"group__error.html#ggafd27986ce4cd9eeaeca8adda83c9eb6babb1116e69e1d651f9f175dbc8bb5fa32\">SP_ERROR_MISSING_CALLBACK</a> =  12, \n<br/>\n&nbsp;&nbsp;<a class=\"el\" href=\"group__error.html#ggafd27986ce4cd9eeaeca8adda83c9eb6bac9f65a7270391d35342ca9e6c01d519d\">SP_ERROR_INVALID_INDATA</a> =  13, \n<br/>\n&nbsp;&nbsp;<a class=\"el\" href=\"group__error.html#ggafd27986ce4cd9eeaeca8adda83c9eb6ba44b3f132578cbf9a43b5c048efcf63a2\">SP_ERROR_INDEX_OUT_OF_RANGE</a> =  14, \n<br/>\n&nbsp;&nbsp;<a class=\"el\" href=\"group__error.html#ggafd27986ce4cd9eeaeca8adda83c9eb6ba96c08adfcda17005c63142cd4e4cd9bb\">SP_ERROR_USER_NEEDS_PREMIUM</a> =  15, \n<br/>\n&nbsp;&nbsp;<a class=\"el\" href=\"group__error.html#ggafd27986ce4cd9eeaeca8adda83c9eb6baf139c18351a543862bd9393ccebc5f91\">SP_ERROR_OTHER_TRANSIENT</a> =  16, \n<br/>\n&nbsp;&nbsp;<a class=\"el\" href=\"group__error.html#ggafd27986ce4cd9eeaeca8adda83c9eb6ba17f54c30d01baedc24547e62ed417cdd\">SP_ERROR_IS_LOADING</a> =  17, \n<br/>\n&nbsp;&nbsp;<a class=\"el\" href=\"group__error.html#ggafd27986ce4cd9eeaeca8adda83c9eb6ba71307cc7b8460042603f3f322d1096f4\">SP_ERROR_NO_STREAM_AVAILABLE</a> =  18, \n<br/>\n&nbsp;&nbsp;<a class=\"el\" href=\"group__error.html#ggafd27986ce4cd9eeaeca8adda83c9eb6baaddac1f3b82e905711ab9ffe5b4b0329\">SP_ERROR_PERMISSION_DENIED</a> =  19, \n<br/>\n&nbsp;&nbsp;<a class=\"el\" href=\"group__error.html#ggafd27986ce4cd9eeaeca8adda83c9eb6baa4bdf4298c9653549464d21ee528c881\">SP_ERROR_INBOX_IS_FULL</a> =  20, \n<br/>\n&nbsp;&nbsp;<a class=\"el\" href=\"group__error.html#ggafd27986ce4cd9eeaeca8adda83c9eb6ba3b8851ee3ba2bd7ad1fe377d94ac38c0\">SP_ERROR_NO_CACHE</a> =  21, \n<br/>\n&nbsp;&nbsp;<a class=\"el\" href=\"group__error.html#ggafd27986ce4cd9eeaeca8adda83c9eb6baf8ade144869c958de534ecec9f9a36a9\">SP_ERROR_NO_SUCH_USER</a> =  22, \n<br/>\n&nbsp;&nbsp;<a class=\"el\" href=\"group__error.html#ggafd27986ce4cd9eeaeca8adda83c9eb6ba9ad34b997313d790f142f24e77e78e2d\">SP_ERROR_NO_CREDENTIALS</a> =  23, \n<br/>\n&nbsp;&nbsp;<a class=\"el\" href=\"group__error.html#ggafd27986ce4cd9eeaeca8adda83c9eb6ba8fda4dd3ee6ac931337a871fbee02978\">SP_ERROR_NETWORK_DISABLED</a> =  24, \n<br/>\n&nbsp;&nbsp;<a class=\"el\" href=\"group__error.html#ggafd27986ce4cd9eeaeca8adda83c9eb6ba846d94ada9e8db0c2bd5153f5801afa2\">SP_ERROR_INVALID_DEVICE_ID</a> =  25, \n<br/>\n&nbsp;&nbsp;<a class=\"el\" href=\"group__error.html#ggafd27986ce4cd9eeaeca8adda83c9eb6badb3af1736912156cbe0b1e39eaeee1c8\">SP_ERROR_CANT_OPEN_TRACE_FILE</a> =  26, \n<br/>\n&nbsp;&nbsp;<a class=\"el\" href=\"group__error.html#ggafd27986ce4cd9eeaeca8adda83c9eb6ba46c3b6173bb5b09445164402ac5ed81f\">SP_ERROR_APPLICATION_BANNED</a> =  27, \n<br/>\n&nbsp;&nbsp;<a class=\"el\" href=\"group__error.html#ggafd27986ce4cd9eeaeca8adda83c9eb6ba32fd1f63fd4dc7ec50bd11791f02953f\">SP_ERROR_OFFLINE_TOO_MANY_TRACKS</a> =  31, \n<br/>\n&nbsp;&nbsp;<a class=\"el\" href=\"group__error.html#ggafd27986ce4cd9eeaeca8adda83c9eb6bae6b9d9b013f1243548e4fbcf961559ff\">SP_ERROR_OFFLINE_DISK_CACHE</a> =  32, \n<br/>\n&nbsp;&nbsp;<a class=\"el\" href=\"group__error.html#ggafd27986ce4cd9eeaeca8adda83c9eb6ba7e16a1962fd4de081d73dc4a4e32eb04\">SP_ERROR_OFFLINE_EXPIRED</a> =  33, \n<br/>\n&nbsp;&nbsp;<a class=\"el\" href=\"group__error.html#ggafd27986ce4cd9eeaeca8adda83c9eb6bae102b46f4fae3b7b6b34e21ea80d656f\">SP_ERROR_OFFLINE_NOT_ALLOWED</a> =  34, \n<br/>\n&nbsp;&nbsp;<a class=\"el\" href=\"group__error.html#ggafd27986ce4cd9eeaeca8adda83c9eb6ba2c87afb46df21783f172a06b2c25d8f9\">SP_ERROR_OFFLINE_LICENSE_LOST</a> =  35, \n<br/>\n&nbsp;&nbsp;<a class=\"el\" href=\"group__error.html#ggafd27986ce4cd9eeaeca8adda83c9eb6ba9149b343017c0dea431839c8b4d9198c\">SP_ERROR_OFFLINE_LICENSE_ERROR</a> =  36, \n<br/>\n&nbsp;&nbsp;<a class=\"el\" href=\"group__error.html#ggafd27986ce4cd9eeaeca8adda83c9eb6baf588c0f7a2d8d11acea28ac2a4de43c4\">SP_ERROR_LASTFM_AUTH_ERROR</a> =  39, \n<br/>\n&nbsp;&nbsp;<a class=\"el\" href=\"group__error.html#ggafd27986ce4cd9eeaeca8adda83c9eb6ba7f8be4d478e51d2b205157c7c538a3e5\">SP_ERROR_INVALID_ARGUMENT</a> =  40, \n<br/>\n&nbsp;&nbsp;<a class=\"el\" href=\"group__error.html#ggafd27986ce4cd9eeaeca8adda83c9eb6ba73d533e0f25f4ba4cecd6d2e2502b80b\">SP_ERROR_SYSTEM_FAILURE</a> =  41\n<br/>\n }</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">enum &nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__session.html#gabf77bb5a124d5a6ee9a12c86abbc0d34\">sp_connectionstate</a> { <br/>\n&nbsp;&nbsp;<a class=\"el\" href=\"group__session.html#ggabf77bb5a124d5a6ee9a12c86abbc0d34ae31e9958a98211ecff5ecbcf7041dfa5\">SP_CONNECTION_STATE_LOGGED_OUT</a> =  0, \n<br/>\n&nbsp;&nbsp;<a class=\"el\" href=\"group__session.html#ggabf77bb5a124d5a6ee9a12c86abbc0d34a88ae17b4168184e62e4c190c289c47c5\">SP_CONNECTION_STATE_LOGGED_IN</a> =  1, \n<br/>\n&nbsp;&nbsp;<a class=\"el\" href=\"group__session.html#ggabf77bb5a124d5a6ee9a12c86abbc0d34ad1a6eb721675af4613f823c091538a8c\">SP_CONNECTION_STATE_DISCONNECTED</a> =  2, \n<br/>\n&nbsp;&nbsp;<a class=\"el\" href=\"group__session.html#ggabf77bb5a124d5a6ee9a12c86abbc0d34a4ddf57518007eef86b06f496d7059484\">SP_CONNECTION_STATE_UNDEFINED</a> =  3, \n<br/>\n&nbsp;&nbsp;<a class=\"el\" href=\"group__session.html#ggabf77bb5a124d5a6ee9a12c86abbc0d34a63099ef9185ba287fcd2e77be3c47d8f\">SP_CONNECTION_STATE_OFFLINE</a> =  4\n<br/>\n }</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">enum &nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__session.html#ga087d21080010768316cfb55d938eb94d\">sp_sampletype</a> { <a class=\"el\" href=\"group__session.html#gga087d21080010768316cfb55d938eb94daa829b269d191cca95ecb02c2bc59da42\">SP_SAMPLETYPE_INT16_NATIVE_ENDIAN</a> =  0\n }</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">enum &nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__session.html#ga77ddd919314a7bb16140569af7a38fe2\">sp_bitrate</a> { <br/>\n&nbsp;&nbsp;<a class=\"el\" href=\"group__session.html#gga77ddd919314a7bb16140569af7a38fe2a5b5c794224972f833a4b7eec9d7909c9\">SP_BITRATE_160k</a> =  0, \n<br/>\n&nbsp;&nbsp;<a class=\"el\" href=\"group__session.html#gga77ddd919314a7bb16140569af7a38fe2a9383c0dc9faefd2cbb38c3b9342c47e0\">SP_BITRATE_320k</a> =  1, \n<br/>\n&nbsp;&nbsp;<a class=\"el\" href=\"group__session.html#gga77ddd919314a7bb16140569af7a38fe2ad815a35af7e6bb5e2ef29418af62759b\">SP_BITRATE_96k</a> =  2\n<br/>\n }</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">enum &nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__session.html#gafdd7117213605e6f2671c4f289b44609\">sp_playlist_type</a> { <br/>\n&nbsp;&nbsp;<a class=\"el\" href=\"group__session.html#ggafdd7117213605e6f2671c4f289b44609a6bd6bf9b62018fa9bbf969835c2f3077\">SP_PLAYLIST_TYPE_PLAYLIST</a> =  0, \n<br/>\n&nbsp;&nbsp;<a class=\"el\" href=\"group__session.html#ggafdd7117213605e6f2671c4f289b44609a4d3266991787f9438deb9de83d9200da\">SP_PLAYLIST_TYPE_START_FOLDER</a> =  1, \n<br/>\n&nbsp;&nbsp;<a class=\"el\" href=\"group__session.html#ggafdd7117213605e6f2671c4f289b44609a3ec52ad1d99d8e32e1b9de31e3f5187a\">SP_PLAYLIST_TYPE_END_FOLDER</a> =  2, \n<br/>\n&nbsp;&nbsp;<a class=\"el\" href=\"group__session.html#ggafdd7117213605e6f2671c4f289b44609ad4f860ef76154e3e2c0d9da2f57a2784\">SP_PLAYLIST_TYPE_PLACEHOLDER</a> =  3\n<br/>\n }</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">enum &nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__session.html#ga99e8e9176ce40fff08a9be8b944edb09\">sp_search_type</a> </td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">enum &nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__session.html#ga811fa52ed0fdb5cda732682e27e40417\">sp_playlist_offline_status</a> { <br/>\n&nbsp;&nbsp;<a class=\"el\" href=\"group__session.html#gga811fa52ed0fdb5cda732682e27e40417abef62e4e3a4af8827fed7fe3aa733ca0\">SP_PLAYLIST_OFFLINE_STATUS_NO</a> =  0, \n<br/>\n&nbsp;&nbsp;<a class=\"el\" href=\"group__session.html#gga811fa52ed0fdb5cda732682e27e40417affed38ac820e084b96fb48e3d1939584\">SP_PLAYLIST_OFFLINE_STATUS_YES</a> =  1, \n<br/>\n&nbsp;&nbsp;<a class=\"el\" href=\"group__session.html#gga811fa52ed0fdb5cda732682e27e40417abc999c70761d392b26753708e9a2cfa1\">SP_PLAYLIST_OFFLINE_STATUS_DOWNLOADING</a> =  2, \n<br/>\n&nbsp;&nbsp;<a class=\"el\" href=\"group__session.html#gga811fa52ed0fdb5cda732682e27e40417a7d929bbf4f1df3633b283e39b9c95919\">SP_PLAYLIST_OFFLINE_STATUS_WAITING</a> =  3\n<br/>\n }</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">enum &nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__session.html#gad7d9465769597b2a379ac704099adfdf\">sp_availability</a> { <br/>\n&nbsp;&nbsp;<a class=\"el\" href=\"group__session.html#ggad7d9465769597b2a379ac704099adfdfa44bc1e6f138910b3f8dbd309325e0077\">SP_TRACK_AVAILABILITY_UNAVAILABLE</a> =  0, \n<br/>\n&nbsp;&nbsp;<a class=\"el\" href=\"group__session.html#ggad7d9465769597b2a379ac704099adfdfa3b837ba6d740b5650b0113734a3b2ff7\">SP_TRACK_AVAILABILITY_AVAILABLE</a> =  1, \n<br/>\n&nbsp;&nbsp;<a class=\"el\" href=\"group__session.html#ggad7d9465769597b2a379ac704099adfdfae7b2cfafa10288ecc50df97621bbe940\">SP_TRACK_AVAILABILITY_NOT_STREAMABLE</a> =  2, \n<br/>\n&nbsp;&nbsp;<a class=\"el\" href=\"group__session.html#ggad7d9465769597b2a379ac704099adfdfaeb5d63e89c543f513cd3054969e50914\">SP_TRACK_AVAILABILITY_BANNED_BY_ARTIST</a> =  3\n<br/>\n }</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">enum &nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__session.html#gaeaa41aad3c0047409996a6ec3b03203f\">sp_track_offline_status</a> { <br/>\n&nbsp;&nbsp;<a class=\"el\" href=\"group__session.html#ggaeaa41aad3c0047409996a6ec3b03203faad1a1cba82ce9f9be678f4d1042eddec\">SP_TRACK_OFFLINE_NO</a> =  0, \n<br/>\n&nbsp;&nbsp;<a class=\"el\" href=\"group__session.html#ggaeaa41aad3c0047409996a6ec3b03203fa1fdd2a518dcdc072cfca27a0ca4f2581\">SP_TRACK_OFFLINE_WAITING</a> =  1, \n<br/>\n&nbsp;&nbsp;<a class=\"el\" href=\"group__session.html#ggaeaa41aad3c0047409996a6ec3b03203fa7dcf6dfc56a8421200451d07a476f370\">SP_TRACK_OFFLINE_DOWNLOADING</a> =  2, \n<br/>\n&nbsp;&nbsp;<a class=\"el\" href=\"group__session.html#ggaeaa41aad3c0047409996a6ec3b03203fac54d46cbc73de7686a1ad8daf269532a\">SP_TRACK_OFFLINE_DONE</a> =  3, \n<br/>\n&nbsp;&nbsp;<a class=\"el\" href=\"group__session.html#ggaeaa41aad3c0047409996a6ec3b03203fa86618798c266540bdc889dd037a52631\">SP_TRACK_OFFLINE_ERROR</a> =  4, \n<br/>\n&nbsp;&nbsp;<a class=\"el\" href=\"group__session.html#ggaeaa41aad3c0047409996a6ec3b03203fa00fe430030fb6a8a49a46c11cca7326c\">SP_TRACK_OFFLINE_DONE_EXPIRED</a> =  5, \n<br/>\n&nbsp;&nbsp;<a class=\"el\" href=\"group__session.html#ggaeaa41aad3c0047409996a6ec3b03203fa405a9b7a3fa489ad2dadbb108794e247\">SP_TRACK_OFFLINE_LIMIT_EXCEEDED</a> =  6, \n<br/>\n&nbsp;&nbsp;<a class=\"el\" href=\"group__session.html#ggaeaa41aad3c0047409996a6ec3b03203fa5f3e19627de4509ae4a3864fd29edee6\">SP_TRACK_OFFLINE_DONE_RESYNC</a> =  7\n<br/>\n }</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">enum &nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__session.html#ga61bc424465d776af3ceeb69eee2bb492\">sp_image_size</a> { <br/>\n&nbsp;&nbsp;<a class=\"el\" href=\"group__session.html#gga61bc424465d776af3ceeb69eee2bb492ad20c808fd1f8180d1f49f643975d1dd7\">SP_IMAGE_SIZE_NORMAL</a> =  0, \n<br/>\n&nbsp;&nbsp;<a class=\"el\" href=\"group__session.html#gga61bc424465d776af3ceeb69eee2bb492ab9340b1bcf2129c3ad1328ea617d547f\">SP_IMAGE_SIZE_SMALL</a> =  1, \n<br/>\n&nbsp;&nbsp;<a class=\"el\" href=\"group__session.html#gga61bc424465d776af3ceeb69eee2bb492a0a0b624afbb2a66ee3d7954202b89721\">SP_IMAGE_SIZE_LARGE</a> =  2\n<br/>\n }</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">enum &nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__session.html#ga3e8773baeb94189b9a1ff27d6a5e3553\">sp_connection_type</a> { <br/>\n&nbsp;&nbsp;<a class=\"el\" href=\"group__session.html#gga3e8773baeb94189b9a1ff27d6a5e3553af949fae9bc12f47b99ef290fa9b5d8a7\">SP_CONNECTION_TYPE_UNKNOWN</a> =  0, \n<br/>\n&nbsp;&nbsp;<a class=\"el\" href=\"group__session.html#gga3e8773baeb94189b9a1ff27d6a5e3553aa7aae7ae3f7c471ece1c6aa2705d046c\">SP_CONNECTION_TYPE_NONE</a> =  1, \n<br/>\n&nbsp;&nbsp;<a class=\"el\" href=\"group__session.html#gga3e8773baeb94189b9a1ff27d6a5e3553a3ca3e6a85ac9d497914c35620ad5179d\">SP_CONNECTION_TYPE_MOBILE</a> =  2, \n<br/>\n&nbsp;&nbsp;<a class=\"el\" href=\"group__session.html#gga3e8773baeb94189b9a1ff27d6a5e3553a05b41bbfd369f9030a7daafc9395116e\">SP_CONNECTION_TYPE_MOBILE_ROAMING</a> =  3, \n<br/>\n&nbsp;&nbsp;<a class=\"el\" href=\"group__session.html#gga3e8773baeb94189b9a1ff27d6a5e3553a31d2cad7379f1bc2eeedd24c40541cb9\">SP_CONNECTION_TYPE_WIFI</a> =  4, \n<br/>\n&nbsp;&nbsp;<a class=\"el\" href=\"group__session.html#gga3e8773baeb94189b9a1ff27d6a5e3553a4f9f0c09e59af4114bb369ebcc474710\">SP_CONNECTION_TYPE_WIRED</a> =  5\n<br/>\n }</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">enum &nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__session.html#gad275d696685b2ad9ff1a2c3e16af6502\">sp_connection_rules</a> { <br/>\n&nbsp;&nbsp;<a class=\"el\" href=\"group__session.html#ggad275d696685b2ad9ff1a2c3e16af6502aa39a1c21c17c55cd1547bc900ae2d386\">SP_CONNECTION_RULE_NETWORK</a> =  0x1, \n<br/>\n&nbsp;&nbsp;<a class=\"el\" href=\"group__session.html#ggad275d696685b2ad9ff1a2c3e16af6502af2772ba84ee7e410ad99708a11955670\">SP_CONNECTION_RULE_NETWORK_IF_ROAMING</a> =  0x2, \n<br/>\n&nbsp;&nbsp;<a class=\"el\" href=\"group__session.html#ggad275d696685b2ad9ff1a2c3e16af6502a91a946573c44de44d74e9d20dbce4c74\">SP_CONNECTION_RULE_ALLOW_SYNC_OVER_MOBILE</a> =  0x4, \n<br/>\n&nbsp;&nbsp;<a class=\"el\" href=\"group__session.html#ggad275d696685b2ad9ff1a2c3e16af6502a548f3734832ec65a992e598d8b91633d\">SP_CONNECTION_RULE_ALLOW_SYNC_OVER_WIFI</a> =  0x8\n<br/>\n }</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">enum &nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__session.html#gac86504cc9e8cadbc30c8aa8dbf355034\">sp_artistbrowse_type</a> { <br/>\n&nbsp;&nbsp;<a class=\"el\" href=\"group__session.html#ggac86504cc9e8cadbc30c8aa8dbf355034a2914168528aded818177c013a0dd7e87\">SP_ARTISTBROWSE_FULL</a>, \n<br/>\n&nbsp;&nbsp;<a class=\"el\" href=\"group__session.html#ggac86504cc9e8cadbc30c8aa8dbf355034afbad1e58606b3230dce5bc3320c95d12\">SP_ARTISTBROWSE_NO_TRACKS</a>, \n<br/>\n&nbsp;&nbsp;<a class=\"el\" href=\"group__session.html#ggac86504cc9e8cadbc30c8aa8dbf355034ac0032981f8dbf44c022e6a7ab1672167\">SP_ARTISTBROWSE_NO_ALBUMS</a>\n<br/>\n }</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">enum &nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__link.html#gabe9611f04086cdbed6e4e6e1fd913b98\">sp_linktype</a> { <br/>\n&nbsp;&nbsp;<a class=\"el\" href=\"group__link.html#ggabe9611f04086cdbed6e4e6e1fd913b98a88b0098486cde586b4dcffb623ac6e63\">SP_LINKTYPE_INVALID</a> =  0, \n<br/>\n&nbsp;&nbsp;<a class=\"el\" href=\"group__link.html#ggabe9611f04086cdbed6e4e6e1fd913b98a5911dbb7258ed160b2f9c114cef152f1\">SP_LINKTYPE_TRACK</a> =  1, \n<br/>\n&nbsp;&nbsp;<a class=\"el\" href=\"group__link.html#ggabe9611f04086cdbed6e4e6e1fd913b98a7716eb95eed852d08300e6e64febc7f3\">SP_LINKTYPE_ALBUM</a> =  2, \n<br/>\n&nbsp;&nbsp;<a class=\"el\" href=\"group__link.html#ggabe9611f04086cdbed6e4e6e1fd913b98a4402b3b001aebb39fd55296f83c60b7e\">SP_LINKTYPE_ARTIST</a> =  3, \n<br/>\n&nbsp;&nbsp;<a class=\"el\" href=\"group__link.html#ggabe9611f04086cdbed6e4e6e1fd913b98ad5909ab9b1cca702163e116b04b6ee8e\">SP_LINKTYPE_SEARCH</a> =  4, \n<br/>\n&nbsp;&nbsp;<a class=\"el\" href=\"group__link.html#ggabe9611f04086cdbed6e4e6e1fd913b98a2640ed065a64b6a9f67e71bbeb2af2dd\">SP_LINKTYPE_PLAYLIST</a> =  5, \n<br/>\n&nbsp;&nbsp;<a class=\"el\" href=\"group__link.html#ggabe9611f04086cdbed6e4e6e1fd913b98ab7a356adce8b1ea34daf21532c7b50e6\">SP_LINKTYPE_PROFILE</a> =  6, \n<br/>\n&nbsp;&nbsp;<a class=\"el\" href=\"group__link.html#ggabe9611f04086cdbed6e4e6e1fd913b98ab649bd86d0fc55ab3fafed3050261353\">SP_LINKTYPE_STARRED</a> =  7, \n<br/>\n&nbsp;&nbsp;<a class=\"el\" href=\"group__link.html#ggabe9611f04086cdbed6e4e6e1fd913b98a0698cd0123190c7af55daf79bb642805\">SP_LINKTYPE_LOCALTRACK</a> =  8, \n<br/>\n&nbsp;&nbsp;<a class=\"el\" href=\"group__link.html#ggabe9611f04086cdbed6e4e6e1fd913b98a1b20b8e2b8773df47b241dc7d28ea0e8\">SP_LINKTYPE_IMAGE</a> =  9\n<br/>\n }</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">enum &nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__album.html#ga019b49a9d1633b61daa79c80ea01d5c3\">sp_albumtype</a> { <br/>\n&nbsp;&nbsp;<a class=\"el\" href=\"group__album.html#gga019b49a9d1633b61daa79c80ea01d5c3ad1693d93a2c05c053fc4fd77886af8dd\">SP_ALBUMTYPE_ALBUM</a> =  0, \n<br/>\n&nbsp;&nbsp;<a class=\"el\" href=\"group__album.html#gga019b49a9d1633b61daa79c80ea01d5c3a3b6f78b733f1bc18a5e4fa18c020fc73\">SP_ALBUMTYPE_SINGLE</a> =  1, \n<br/>\n&nbsp;&nbsp;<a class=\"el\" href=\"group__album.html#gga019b49a9d1633b61daa79c80ea01d5c3a8fee6ba46e8876037f4f2e46c6d6c6af\">SP_ALBUMTYPE_COMPILATION</a> =  2, \n<br/>\n&nbsp;&nbsp;<a class=\"el\" href=\"group__album.html#gga019b49a9d1633b61daa79c80ea01d5c3ad564ed5f1f0659929fe5ec700513873f\">SP_ALBUMTYPE_UNKNOWN</a> =  3\n<br/>\n }</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">enum &nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__image.html#ga2cda19baf2460da5e81fb1917f54626b\">sp_imageformat</a> { <br/>\n&nbsp;&nbsp;<a class=\"el\" href=\"group__image.html#gga2cda19baf2460da5e81fb1917f54626ba2fec8a1b400bd6cd5396b9852e4279b6\">SP_IMAGE_FORMAT_UNKNOWN</a> =  -1, \n<br/>\n&nbsp;&nbsp;<a class=\"el\" href=\"group__image.html#gga2cda19baf2460da5e81fb1917f54626ba6263674800bea702c4d913d4b07c135d\">SP_IMAGE_FORMAT_JPEG</a> =  0\n<br/>\n }</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">enum &nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__user.html#ga6af84143c0622b6fc5539bb1ae111e5b\">sp_relation_type</a> { <br/>\n&nbsp;&nbsp;<a class=\"el\" href=\"group__user.html#gga6af84143c0622b6fc5539bb1ae111e5ba18f24164eef0e687b351c2aa6753e35e\">SP_RELATION_TYPE_UNKNOWN</a> =  0, \n<br/>\n&nbsp;&nbsp;<a class=\"el\" href=\"group__user.html#gga6af84143c0622b6fc5539bb1ae111e5bad9805f100828a9d3b64c3cc66f2ac5c1\">SP_RELATION_TYPE_NONE</a> =  1, \n<br/>\n&nbsp;&nbsp;<a class=\"el\" href=\"group__user.html#gga6af84143c0622b6fc5539bb1ae111e5ba06b2f38745c467e7e362c7744cb74205\">SP_RELATION_TYPE_UNIDIRECTIONAL</a> =  2, \n<br/>\n&nbsp;&nbsp;<a class=\"el\" href=\"group__user.html#gga6af84143c0622b6fc5539bb1ae111e5ba4bfef63cabd016cf1e6b11347a05d389\">SP_RELATION_TYPE_BIDIRECTIONAL</a> =  3\n<br/>\n }</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">enum &nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__toplist.html#ga220f32522efb2828e4f8ffb949af234a\">sp_toplisttype</a> { <br/>\n&nbsp;&nbsp;<a class=\"el\" href=\"group__toplist.html#gga220f32522efb2828e4f8ffb949af234aa41523e58badf9e3901beea3f53e5d28e\">SP_TOPLIST_TYPE_ARTISTS</a> =  0, \n<br/>\n&nbsp;&nbsp;<a class=\"el\" href=\"group__toplist.html#gga220f32522efb2828e4f8ffb949af234aae8002818ef10eb2c75ec2058ce11cf6b\">SP_TOPLIST_TYPE_ALBUMS</a> =  1, \n<br/>\n&nbsp;&nbsp;<a class=\"el\" href=\"group__toplist.html#gga220f32522efb2828e4f8ffb949af234aa6a85f8384ec77cb9cb5746966b0f0e28\">SP_TOPLIST_TYPE_TRACKS</a> =  2\n<br/>\n }</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">enum &nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__toplist.html#ga6fa5cfed2cbb33f2f64542d0b63f6c8d\">sp_toplistregion</a> { <br/>\n&nbsp;&nbsp;<a class=\"el\" href=\"group__toplist.html#gga6fa5cfed2cbb33f2f64542d0b63f6c8da9e9136541401041c7d5c37708b7a927f\">SP_TOPLIST_REGION_EVERYWHERE</a> =  0, \n<br/>\n&nbsp;&nbsp;<a class=\"el\" href=\"group__toplist.html#gga6fa5cfed2cbb33f2f64542d0b63f6c8da6912eff58c71f5c74b78f48af5305375\">SP_TOPLIST_REGION_USER</a> =  1\n<br/>\n }</td></tr>\n<tr><td colspan=\"2\"><h2><a name=\"func-members\"></a>\nFunctions</h2></td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">const char *&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__error.html#ga983dee341d3c2008830513b7cffe7bf3\">sp_error_message</a> (<a class=\"el\" href=\"group__error.html#gafd27986ce4cd9eeaeca8adda83c9eb6b\">sp_error</a> error)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__error.html#gafd27986ce4cd9eeaeca8adda83c9eb6b\">sp_error</a>&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__session.html#gaf2891f2daced4ff6da84219d6376b3aa\">sp_session_create</a> (const <a class=\"el\" href=\"structsp__session__config.html\">sp_session_config</a> *config, <a class=\"el\" href=\"group__types.html#ga70dd19c6f824cf6a159575aa4c128b53\">sp_session</a> **sess)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__error.html#gafd27986ce4cd9eeaeca8adda83c9eb6b\">sp_error</a>&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__session.html#gab81c540b76f7425a9cc0dbf270c09674\">sp_session_release</a> (<a class=\"el\" href=\"group__types.html#ga70dd19c6f824cf6a159575aa4c128b53\">sp_session</a> *sess)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__error.html#gafd27986ce4cd9eeaeca8adda83c9eb6b\">sp_error</a>&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__session.html#ga4533a992a120cacb109c892a852afe2a\">sp_session_login</a> (<a class=\"el\" href=\"group__types.html#ga70dd19c6f824cf6a159575aa4c128b53\">sp_session</a> *session, const char *username, const char *password, bool remember_me, const char *blob)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__error.html#gafd27986ce4cd9eeaeca8adda83c9eb6b\">sp_error</a>&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__session.html#gae1bc9bebd230226c3d48925cd1be6edf\">sp_session_relogin</a> (<a class=\"el\" href=\"group__types.html#ga70dd19c6f824cf6a159575aa4c128b53\">sp_session</a> *session)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">int&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__session.html#gab349c7bfe59e10e167bd75c20df9fc97\">sp_session_remembered_user</a> (<a class=\"el\" href=\"group__types.html#ga70dd19c6f824cf6a159575aa4c128b53\">sp_session</a> *session, char *buffer, size_t buffer_size)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">const char *&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__session.html#gac7a365c2166738909cdb901edebc3f70\">sp_session_user_name</a> (<a class=\"el\" href=\"group__types.html#ga70dd19c6f824cf6a159575aa4c128b53\">sp_session</a> *session)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__error.html#gafd27986ce4cd9eeaeca8adda83c9eb6b\">sp_error</a>&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__session.html#ga61e6b796d9e07682c018e888b901a191\">sp_session_forget_me</a> (<a class=\"el\" href=\"group__types.html#ga70dd19c6f824cf6a159575aa4c128b53\">sp_session</a> *session)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__types.html#gaed2dbaa1eebd6752f76613daad9158bc\">sp_user</a> *&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__session.html#ga267bbcae24b6bb1fd56de56678a5f455\">sp_session_user</a> (<a class=\"el\" href=\"group__types.html#ga70dd19c6f824cf6a159575aa4c128b53\">sp_session</a> *session)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__error.html#gafd27986ce4cd9eeaeca8adda83c9eb6b\">sp_error</a>&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__session.html#gab7f08ca0939985b30ae2d1ed9db1d726\">sp_session_logout</a> (<a class=\"el\" href=\"group__types.html#ga70dd19c6f824cf6a159575aa4c128b53\">sp_session</a> *session)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__error.html#gafd27986ce4cd9eeaeca8adda83c9eb6b\">sp_error</a>&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__session.html#ga34005bb06ee3de8ee4221597a0335cca\">sp_session_flush_caches</a> (<a class=\"el\" href=\"group__types.html#ga70dd19c6f824cf6a159575aa4c128b53\">sp_session</a> *session)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__session.html#gabf77bb5a124d5a6ee9a12c86abbc0d34\">sp_connectionstate</a>&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__session.html#ga34a7c9527705ab7d23b742006d81ea35\">sp_session_connectionstate</a> (<a class=\"el\" href=\"group__types.html#ga70dd19c6f824cf6a159575aa4c128b53\">sp_session</a> *session)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">void *&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__session.html#gabfb3f59b20ae0b225e154eb9095152b2\">sp_session_userdata</a> (<a class=\"el\" href=\"group__types.html#ga70dd19c6f824cf6a159575aa4c128b53\">sp_session</a> *session)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__error.html#gafd27986ce4cd9eeaeca8adda83c9eb6b\">sp_error</a>&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__session.html#ga6f27c55d1ce9f3f794fcce7bee7adfea\">sp_session_set_cache_size</a> (<a class=\"el\" href=\"group__types.html#ga70dd19c6f824cf6a159575aa4c128b53\">sp_session</a> *session, size_t size)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__error.html#gafd27986ce4cd9eeaeca8adda83c9eb6b\">sp_error</a>&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__session.html#gaff27cb730db6debf55e750e39e7fadd7\">sp_session_process_events</a> (<a class=\"el\" href=\"group__types.html#ga70dd19c6f824cf6a159575aa4c128b53\">sp_session</a> *session, int *next_timeout)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__error.html#gafd27986ce4cd9eeaeca8adda83c9eb6b\">sp_error</a>&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__session.html#gac73bf2c569a43d824439b557d5e4b293\">sp_session_player_load</a> (<a class=\"el\" href=\"group__types.html#ga70dd19c6f824cf6a159575aa4c128b53\">sp_session</a> *session, <a class=\"el\" href=\"group__types.html#ga47bbd2262f0c8b5d7147af7d62198e48\">sp_track</a> *track)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__error.html#gafd27986ce4cd9eeaeca8adda83c9eb6b\">sp_error</a>&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__session.html#ga3430cd4f11541868d3f83eaa31aecf44\">sp_session_player_seek</a> (<a class=\"el\" href=\"group__types.html#ga70dd19c6f824cf6a159575aa4c128b53\">sp_session</a> *session, int offset)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__error.html#gafd27986ce4cd9eeaeca8adda83c9eb6b\">sp_error</a>&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__session.html#gab66c5915967e4f90db945b118e620624\">sp_session_player_play</a> (<a class=\"el\" href=\"group__types.html#ga70dd19c6f824cf6a159575aa4c128b53\">sp_session</a> *session, bool play)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__error.html#gafd27986ce4cd9eeaeca8adda83c9eb6b\">sp_error</a>&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__session.html#gafa7ee2803f119451bb8be3bf28746975\">sp_session_player_unload</a> (<a class=\"el\" href=\"group__types.html#ga70dd19c6f824cf6a159575aa4c128b53\">sp_session</a> *session)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__error.html#gafd27986ce4cd9eeaeca8adda83c9eb6b\">sp_error</a>&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__session.html#gaf42e30a1f430ac7c436c7d9f0485368d\">sp_session_player_prefetch</a> (<a class=\"el\" href=\"group__types.html#ga70dd19c6f824cf6a159575aa4c128b53\">sp_session</a> *session, <a class=\"el\" href=\"group__types.html#ga47bbd2262f0c8b5d7147af7d62198e48\">sp_track</a> *track)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__types.html#ga45a2febbe167483e48dab8d606d462d7\">sp_playlistcontainer</a> *&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__session.html#ga319767f0b795f1c46a08390b587c5671\">sp_session_playlistcontainer</a> (<a class=\"el\" href=\"group__types.html#ga70dd19c6f824cf6a159575aa4c128b53\">sp_session</a> *session)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__types.html#ga1bcf54cbc117a20ab2c15e59eb3a8174\">sp_playlist</a> *&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__session.html#gac72ccb51031c846101134b73195bb9ec\">sp_session_inbox_create</a> (<a class=\"el\" href=\"group__types.html#ga70dd19c6f824cf6a159575aa4c128b53\">sp_session</a> *session)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__types.html#ga1bcf54cbc117a20ab2c15e59eb3a8174\">sp_playlist</a> *&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__session.html#ga02391c9e28cff0a602f7139542e0238f\">sp_session_starred_create</a> (<a class=\"el\" href=\"group__types.html#ga70dd19c6f824cf6a159575aa4c128b53\">sp_session</a> *session)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__types.html#ga1bcf54cbc117a20ab2c15e59eb3a8174\">sp_playlist</a> *&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__session.html#ga9be806a719a6399bfe1fd0d4c125e0eb\">sp_session_starred_for_user_create</a> (<a class=\"el\" href=\"group__types.html#ga70dd19c6f824cf6a159575aa4c128b53\">sp_session</a> *session, const char *canonical_username)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__types.html#ga45a2febbe167483e48dab8d606d462d7\">sp_playlistcontainer</a> *&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__session.html#ga4ad3a1de596a41f275120dad3bb4685d\">sp_session_publishedcontainer_for_user_create</a> (<a class=\"el\" href=\"group__types.html#ga70dd19c6f824cf6a159575aa4c128b53\">sp_session</a> *session, const char *canonical_username)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__error.html#gafd27986ce4cd9eeaeca8adda83c9eb6b\">sp_error</a>&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__session.html#gacd590e095b011af42fb10046117846fe\">sp_session_preferred_bitrate</a> (<a class=\"el\" href=\"group__types.html#ga70dd19c6f824cf6a159575aa4c128b53\">sp_session</a> *session, <a class=\"el\" href=\"group__session.html#ga77ddd919314a7bb16140569af7a38fe2\">sp_bitrate</a> bitrate)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__error.html#gafd27986ce4cd9eeaeca8adda83c9eb6b\">sp_error</a>&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__session.html#ga4bba5f828d6c87692f2c355cc8f07c61\">sp_session_preferred_offline_bitrate</a> (<a class=\"el\" href=\"group__types.html#ga70dd19c6f824cf6a159575aa4c128b53\">sp_session</a> *session, <a class=\"el\" href=\"group__session.html#ga77ddd919314a7bb16140569af7a38fe2\">sp_bitrate</a> bitrate, bool allow_resync)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">bool&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__session.html#ga7913df06394360f255c77fb87af0f1fe\">sp_session_get_volume_normalization</a> (<a class=\"el\" href=\"group__types.html#ga70dd19c6f824cf6a159575aa4c128b53\">sp_session</a> *session)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__error.html#gafd27986ce4cd9eeaeca8adda83c9eb6b\">sp_error</a>&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__session.html#ga4e14f58356d00e3693be84623bf6bd11\">sp_session_set_volume_normalization</a> (<a class=\"el\" href=\"group__types.html#ga70dd19c6f824cf6a159575aa4c128b53\">sp_session</a> *session, bool on)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__error.html#gafd27986ce4cd9eeaeca8adda83c9eb6b\">sp_error</a>&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__session.html#ga42a8f0999316ac7f141926092879ad2f\">sp_session_set_private_session</a> (<a class=\"el\" href=\"group__types.html#ga70dd19c6f824cf6a159575aa4c128b53\">sp_session</a> *session, bool enabled)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">bool&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__session.html#ga72702ee06bc96c074804388d24344149\">sp_session_is_private_session</a> (<a class=\"el\" href=\"group__types.html#ga70dd19c6f824cf6a159575aa4c128b53\">sp_session</a> *session)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__error.html#gafd27986ce4cd9eeaeca8adda83c9eb6b\">sp_error</a>&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__session.html#ga2475a1fbc2eeacccb96b7f36efd36725\">sp_session_set_scrobbling</a> (<a class=\"el\" href=\"group__types.html#ga70dd19c6f824cf6a159575aa4c128b53\">sp_session</a> *session, sp_social_provider provider, sp_scrobbling_state state)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__error.html#gafd27986ce4cd9eeaeca8adda83c9eb6b\">sp_error</a>&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__session.html#ga6a56bc82ff0b369bb6e0f035534ce33d\">sp_session_is_scrobbling</a> (<a class=\"el\" href=\"group__types.html#ga70dd19c6f824cf6a159575aa4c128b53\">sp_session</a> *session, sp_social_provider provider, sp_scrobbling_state *state)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__error.html#gafd27986ce4cd9eeaeca8adda83c9eb6b\">sp_error</a>&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__session.html#ga0fad03ceabcf8d68af78f0f35fcbcc8d\">sp_session_is_scrobbling_possible</a> (<a class=\"el\" href=\"group__types.html#ga70dd19c6f824cf6a159575aa4c128b53\">sp_session</a> *session, sp_social_provider provider, bool *out)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__error.html#gafd27986ce4cd9eeaeca8adda83c9eb6b\">sp_error</a>&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__session.html#ga9e5ee46ef5e75aa462607caac984f2de\">sp_session_set_social_credentials</a> (<a class=\"el\" href=\"group__types.html#ga70dd19c6f824cf6a159575aa4c128b53\">sp_session</a> *session, sp_social_provider provider, const char *username, const char *password)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__error.html#gafd27986ce4cd9eeaeca8adda83c9eb6b\">sp_error</a>&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__session.html#gaf81c61799e0ccdbba048fb79ec050930\">sp_session_set_connection_type</a> (<a class=\"el\" href=\"group__types.html#ga70dd19c6f824cf6a159575aa4c128b53\">sp_session</a> *session, <a class=\"el\" href=\"group__session.html#ga3e8773baeb94189b9a1ff27d6a5e3553\">sp_connection_type</a> type)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__error.html#gafd27986ce4cd9eeaeca8adda83c9eb6b\">sp_error</a>&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__session.html#ga0ac85299c37710321b6d64713e1d6ba8\">sp_session_set_connection_rules</a> (<a class=\"el\" href=\"group__types.html#ga70dd19c6f824cf6a159575aa4c128b53\">sp_session</a> *session, <a class=\"el\" href=\"group__session.html#gad275d696685b2ad9ff1a2c3e16af6502\">sp_connection_rules</a> rules)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">int&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__session.html#gaf535124b4208c279cb98a061834e6411\">sp_offline_tracks_to_sync</a> (<a class=\"el\" href=\"group__types.html#ga70dd19c6f824cf6a159575aa4c128b53\">sp_session</a> *session)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">int&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__session.html#gad6cee58fa44453b7a4fd2ae2266df055\">sp_offline_num_playlists</a> (<a class=\"el\" href=\"group__types.html#ga70dd19c6f824cf6a159575aa4c128b53\">sp_session</a> *session)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">bool&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__session.html#ga02525cd659a34728047cd3801049e822\">sp_offline_sync_get_status</a> (<a class=\"el\" href=\"group__types.html#ga70dd19c6f824cf6a159575aa4c128b53\">sp_session</a> *session, <a class=\"el\" href=\"structsp__offline__sync__status.html\">sp_offline_sync_status</a> *status)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">int&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__session.html#gac36816dc42825db9a5a2fbd2694f20af\">sp_offline_time_left</a> (<a class=\"el\" href=\"group__types.html#ga70dd19c6f824cf6a159575aa4c128b53\">sp_session</a> *session)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">int&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__session.html#ga54c7693afa9be664f3ea870feb0df8d9\">sp_session_user_country</a> (<a class=\"el\" href=\"group__types.html#ga70dd19c6f824cf6a159575aa4c128b53\">sp_session</a> *session)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__types.html#gaf90a23d6b662c96d52ac19f7f4bc1e39\">sp_link</a> *&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__link.html#gaea9c39f35f7986fc9fed4584fa211127\">sp_link_create_from_string</a> (const char *link)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__types.html#gaf90a23d6b662c96d52ac19f7f4bc1e39\">sp_link</a> *&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__link.html#ga82c29419ce70e2b504670e3d45167d5d\">sp_link_create_from_track</a> (<a class=\"el\" href=\"group__types.html#ga47bbd2262f0c8b5d7147af7d62198e48\">sp_track</a> *track, int offset)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__types.html#gaf90a23d6b662c96d52ac19f7f4bc1e39\">sp_link</a> *&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__link.html#ga040627b0df84425947c82cd8890122ad\">sp_link_create_from_album</a> (<a class=\"el\" href=\"group__types.html#ga6fd3e5de729c429fef3ff18ece6dcfad\">sp_album</a> *album)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__types.html#gaf90a23d6b662c96d52ac19f7f4bc1e39\">sp_link</a> *&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__link.html#gaa87e346c29f1077d7a62c364719d4a55\">sp_link_create_from_album_cover</a> (<a class=\"el\" href=\"group__types.html#ga6fd3e5de729c429fef3ff18ece6dcfad\">sp_album</a> *album, <a class=\"el\" href=\"group__session.html#ga61bc424465d776af3ceeb69eee2bb492\">sp_image_size</a> size)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__types.html#gaf90a23d6b662c96d52ac19f7f4bc1e39\">sp_link</a> *&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__link.html#ga3196ce9de3da4f1d5944a0b58bd80540\">sp_link_create_from_artist</a> (<a class=\"el\" href=\"group__types.html#ga31764fbd69618c10be173c6c03d4c1bc\">sp_artist</a> *artist)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__types.html#gaf90a23d6b662c96d52ac19f7f4bc1e39\">sp_link</a> *&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__link.html#gaafb25ee14bfb27f9cbbab1b039d4d225\">sp_link_create_from_artist_portrait</a> (<a class=\"el\" href=\"group__types.html#ga31764fbd69618c10be173c6c03d4c1bc\">sp_artist</a> *artist, <a class=\"el\" href=\"group__session.html#ga61bc424465d776af3ceeb69eee2bb492\">sp_image_size</a> size)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__types.html#gaf90a23d6b662c96d52ac19f7f4bc1e39\">sp_link</a> *&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__link.html#ga32218fbd912ddddbb749cb42a72b6bcd\">sp_link_create_from_artistbrowse_portrait</a> (<a class=\"el\" href=\"group__types.html#gafd3d5aae485f1012ec91b7948e6f9f2b\">sp_artistbrowse</a> *arb, int index)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__types.html#gaf90a23d6b662c96d52ac19f7f4bc1e39\">sp_link</a> *&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__link.html#ga95c97ba4de9c4040047276ad618a108e\">sp_link_create_from_search</a> (<a class=\"el\" href=\"group__types.html#gac95893a6b23d4b19f6f149eed6ead1fd\">sp_search</a> *search)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__types.html#gaf90a23d6b662c96d52ac19f7f4bc1e39\">sp_link</a> *&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__link.html#ga805392bfa8e526eebedc1cf5a7bcae0f\">sp_link_create_from_playlist</a> (<a class=\"el\" href=\"group__types.html#ga1bcf54cbc117a20ab2c15e59eb3a8174\">sp_playlist</a> *playlist)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__types.html#gaf90a23d6b662c96d52ac19f7f4bc1e39\">sp_link</a> *&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__link.html#gaaa78b1750179c17f8152408cea43efef\">sp_link_create_from_user</a> (<a class=\"el\" href=\"group__types.html#gaed2dbaa1eebd6752f76613daad9158bc\">sp_user</a> *user)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__types.html#gaf90a23d6b662c96d52ac19f7f4bc1e39\">sp_link</a> *&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__link.html#gaa85fbea312127db44685b7e9dc492042\">sp_link_create_from_image</a> (<a class=\"el\" href=\"group__types.html#ga61155ca7b1ba941e15490e417441917b\">sp_image</a> *image)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">int&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__link.html#ga9f169be53f098adcf12f7a10b8bd3ef7\">sp_link_as_string</a> (<a class=\"el\" href=\"group__types.html#gaf90a23d6b662c96d52ac19f7f4bc1e39\">sp_link</a> *link, char *buffer, int buffer_size)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__link.html#gabe9611f04086cdbed6e4e6e1fd913b98\">sp_linktype</a>&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__link.html#ga6140f924c696d53469bb8930cd53e1e6\">sp_link_type</a> (<a class=\"el\" href=\"group__types.html#gaf90a23d6b662c96d52ac19f7f4bc1e39\">sp_link</a> *link)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__types.html#ga47bbd2262f0c8b5d7147af7d62198e48\">sp_track</a> *&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__link.html#ga2560687997d7ce0fbf4f05251d87d32a\">sp_link_as_track</a> (<a class=\"el\" href=\"group__types.html#gaf90a23d6b662c96d52ac19f7f4bc1e39\">sp_link</a> *link)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__types.html#ga47bbd2262f0c8b5d7147af7d62198e48\">sp_track</a> *&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__link.html#ga80f6f752832f76c268c0bfd3ca45e6d2\">sp_link_as_track_and_offset</a> (<a class=\"el\" href=\"group__types.html#gaf90a23d6b662c96d52ac19f7f4bc1e39\">sp_link</a> *link, int *offset)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__types.html#ga6fd3e5de729c429fef3ff18ece6dcfad\">sp_album</a> *&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__link.html#gaafa98628d0abadcca27dd3b227c7337b\">sp_link_as_album</a> (<a class=\"el\" href=\"group__types.html#gaf90a23d6b662c96d52ac19f7f4bc1e39\">sp_link</a> *link)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__types.html#ga31764fbd69618c10be173c6c03d4c1bc\">sp_artist</a> *&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__link.html#gab32979d26dcf68936202fa7aed7b6e49\">sp_link_as_artist</a> (<a class=\"el\" href=\"group__types.html#gaf90a23d6b662c96d52ac19f7f4bc1e39\">sp_link</a> *link)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__types.html#gaed2dbaa1eebd6752f76613daad9158bc\">sp_user</a> *&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__link.html#ga3e29975f47fc0a51be813b4774a3d6f3\">sp_link_as_user</a> (<a class=\"el\" href=\"group__types.html#gaf90a23d6b662c96d52ac19f7f4bc1e39\">sp_link</a> *link)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__error.html#gafd27986ce4cd9eeaeca8adda83c9eb6b\">sp_error</a>&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__link.html#gac5a808b15bceed41508bd3863c8f4b3b\">sp_link_add_ref</a> (<a class=\"el\" href=\"group__types.html#gaf90a23d6b662c96d52ac19f7f4bc1e39\">sp_link</a> *link)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__error.html#gafd27986ce4cd9eeaeca8adda83c9eb6b\">sp_error</a>&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__link.html#ga2b06ab16d1f6436cd8d36dbff2b5c022\">sp_link_release</a> (<a class=\"el\" href=\"group__types.html#gaf90a23d6b662c96d52ac19f7f4bc1e39\">sp_link</a> *link)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">bool&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__track.html#ga8b69cf193679c7e00031ae43e61c6a54\">sp_track_is_loaded</a> (<a class=\"el\" href=\"group__types.html#ga47bbd2262f0c8b5d7147af7d62198e48\">sp_track</a> *track)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__error.html#gafd27986ce4cd9eeaeca8adda83c9eb6b\">sp_error</a>&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__track.html#ga947c0f7755b0c4955ca0b0993db0f2b5\">sp_track_error</a> (<a class=\"el\" href=\"group__types.html#ga47bbd2262f0c8b5d7147af7d62198e48\">sp_track</a> *track)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__session.html#gaeaa41aad3c0047409996a6ec3b03203f\">sp_track_offline_status</a>&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__track.html#ga281e0ad4373579c5d24202ea1f93fe7b\">sp_track_offline_get_status</a> (<a class=\"el\" href=\"group__types.html#ga47bbd2262f0c8b5d7147af7d62198e48\">sp_track</a> *track)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__session.html#ga60c7ff53ddbc04c036a23181b7275d69\">sp_track_availability</a>&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__track.html#ga9c78846badae6567fe9f9a3792fd06c8\">sp_track_get_availability</a> (<a class=\"el\" href=\"group__types.html#ga70dd19c6f824cf6a159575aa4c128b53\">sp_session</a> *session, <a class=\"el\" href=\"group__types.html#ga47bbd2262f0c8b5d7147af7d62198e48\">sp_track</a> *track)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">bool&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__track.html#gabcb75da69e0338006bdbd2f2f467f082\">sp_track_is_local</a> (<a class=\"el\" href=\"group__types.html#ga70dd19c6f824cf6a159575aa4c128b53\">sp_session</a> *session, <a class=\"el\" href=\"group__types.html#ga47bbd2262f0c8b5d7147af7d62198e48\">sp_track</a> *track)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">bool&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__track.html#ga4eeb86de13187697cd9dfe0b0934988d\">sp_track_is_autolinked</a> (<a class=\"el\" href=\"group__types.html#ga70dd19c6f824cf6a159575aa4c128b53\">sp_session</a> *session, <a class=\"el\" href=\"group__types.html#ga47bbd2262f0c8b5d7147af7d62198e48\">sp_track</a> *track)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__types.html#ga47bbd2262f0c8b5d7147af7d62198e48\">sp_track</a> *&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__track.html#ga112dca47d0bac39818b55119ef134ffd\">sp_track_get_playable</a> (<a class=\"el\" href=\"group__types.html#ga70dd19c6f824cf6a159575aa4c128b53\">sp_session</a> *session, <a class=\"el\" href=\"group__types.html#ga47bbd2262f0c8b5d7147af7d62198e48\">sp_track</a> *track)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">bool&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__track.html#ga2367d906c578e674d0d470d8c1ee3b33\">sp_track_is_placeholder</a> (<a class=\"el\" href=\"group__types.html#ga47bbd2262f0c8b5d7147af7d62198e48\">sp_track</a> *track)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">bool&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__track.html#gab17d380ac941e102af0f308ad885b3c3\">sp_track_is_starred</a> (<a class=\"el\" href=\"group__types.html#ga70dd19c6f824cf6a159575aa4c128b53\">sp_session</a> *session, <a class=\"el\" href=\"group__types.html#ga47bbd2262f0c8b5d7147af7d62198e48\">sp_track</a> *track)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__error.html#gafd27986ce4cd9eeaeca8adda83c9eb6b\">sp_error</a>&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__track.html#ga34b5a712fb2c683402ff78df73e7545c\">sp_track_set_starred</a> (<a class=\"el\" href=\"group__types.html#ga70dd19c6f824cf6a159575aa4c128b53\">sp_session</a> *session, <a class=\"el\" href=\"group__types.html#ga47bbd2262f0c8b5d7147af7d62198e48\">sp_track</a> *const *tracks, int num_tracks, bool star)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">int&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__track.html#ga0aa945fc43e35d36cc334a52735d83b2\">sp_track_num_artists</a> (<a class=\"el\" href=\"group__types.html#ga47bbd2262f0c8b5d7147af7d62198e48\">sp_track</a> *track)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__types.html#ga31764fbd69618c10be173c6c03d4c1bc\">sp_artist</a> *&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__track.html#ga67cd0c035627a1e4a54642213fdf1d75\">sp_track_artist</a> (<a class=\"el\" href=\"group__types.html#ga47bbd2262f0c8b5d7147af7d62198e48\">sp_track</a> *track, int index)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__types.html#ga6fd3e5de729c429fef3ff18ece6dcfad\">sp_album</a> *&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__track.html#ga39a0f52244472cb2d450ea9ba6807304\">sp_track_album</a> (<a class=\"el\" href=\"group__types.html#ga47bbd2262f0c8b5d7147af7d62198e48\">sp_track</a> *track)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">const char *&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__track.html#ga8eb423d3cc2cbfb743c7f23ffb8d0fad\">sp_track_name</a> (<a class=\"el\" href=\"group__types.html#ga47bbd2262f0c8b5d7147af7d62198e48\">sp_track</a> *track)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">int&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__track.html#gac817937bd8d8355b6a1949b76d0b5560\">sp_track_duration</a> (<a class=\"el\" href=\"group__types.html#ga47bbd2262f0c8b5d7147af7d62198e48\">sp_track</a> *track)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">int&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__track.html#ga4570f08f968edbff519b44d2241d2255\">sp_track_popularity</a> (<a class=\"el\" href=\"group__types.html#ga47bbd2262f0c8b5d7147af7d62198e48\">sp_track</a> *track)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">int&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__track.html#ga9d464ee4a5c8836b59888952b960223a\">sp_track_disc</a> (<a class=\"el\" href=\"group__types.html#ga47bbd2262f0c8b5d7147af7d62198e48\">sp_track</a> *track)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">int&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__track.html#ga25c1df9d32fd58f243397740b29c3f61\">sp_track_index</a> (<a class=\"el\" href=\"group__types.html#ga47bbd2262f0c8b5d7147af7d62198e48\">sp_track</a> *track)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__types.html#ga47bbd2262f0c8b5d7147af7d62198e48\">sp_track</a> *&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__track.html#ga0fb814ef23636fdecda64e3a63b15a23\">sp_localtrack_create</a> (const char *artist, const char *title, const char *album, int length)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__error.html#gafd27986ce4cd9eeaeca8adda83c9eb6b\">sp_error</a>&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__track.html#ga7d86041a2bf75590f55978521c08e38c\">sp_track_add_ref</a> (<a class=\"el\" href=\"group__types.html#ga47bbd2262f0c8b5d7147af7d62198e48\">sp_track</a> *track)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__error.html#gafd27986ce4cd9eeaeca8adda83c9eb6b\">sp_error</a>&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__track.html#gaa11098d82e6c2ae42fc2ea1486e741de\">sp_track_release</a> (<a class=\"el\" href=\"group__types.html#ga47bbd2262f0c8b5d7147af7d62198e48\">sp_track</a> *track)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">bool&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__album.html#ga46fbfa98be12c2f4067d5e679552cfb9\">sp_album_is_loaded</a> (<a class=\"el\" href=\"group__types.html#ga6fd3e5de729c429fef3ff18ece6dcfad\">sp_album</a> *album)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">bool&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__album.html#ga89eb8dc73a76f5e0509b1066426495f7\">sp_album_is_available</a> (<a class=\"el\" href=\"group__types.html#ga6fd3e5de729c429fef3ff18ece6dcfad\">sp_album</a> *album)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__types.html#ga31764fbd69618c10be173c6c03d4c1bc\">sp_artist</a> *&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__album.html#ga42309972141dab10c32d741d357c01de\">sp_album_artist</a> (<a class=\"el\" href=\"group__types.html#ga6fd3e5de729c429fef3ff18ece6dcfad\">sp_album</a> *album)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">const byte *&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__album.html#ga6616ef3df724af185c5eb58e8a0fb808\">sp_album_cover</a> (<a class=\"el\" href=\"group__types.html#ga6fd3e5de729c429fef3ff18ece6dcfad\">sp_album</a> *album, <a class=\"el\" href=\"group__session.html#ga61bc424465d776af3ceeb69eee2bb492\">sp_image_size</a> size)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">const char *&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__album.html#ga0e828c991a8184d60026513f944e19ad\">sp_album_name</a> (<a class=\"el\" href=\"group__types.html#ga6fd3e5de729c429fef3ff18ece6dcfad\">sp_album</a> *album)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">int&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__album.html#ga2aadf934b0af43c3ef6ee98b6a8065fd\">sp_album_year</a> (<a class=\"el\" href=\"group__types.html#ga6fd3e5de729c429fef3ff18ece6dcfad\">sp_album</a> *album)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__album.html#ga019b49a9d1633b61daa79c80ea01d5c3\">sp_albumtype</a>&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__album.html#ga8dceb04a62bdb3ffc112ed0efc359e51\">sp_album_type</a> (<a class=\"el\" href=\"group__types.html#ga6fd3e5de729c429fef3ff18ece6dcfad\">sp_album</a> *album)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__error.html#gafd27986ce4cd9eeaeca8adda83c9eb6b\">sp_error</a>&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__album.html#ga08192dd38d1c628f7b51615fffa33017\">sp_album_add_ref</a> (<a class=\"el\" href=\"group__types.html#ga6fd3e5de729c429fef3ff18ece6dcfad\">sp_album</a> *album)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__error.html#gafd27986ce4cd9eeaeca8adda83c9eb6b\">sp_error</a>&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__album.html#ga5c6e49d04ffb05c722db5e78c9434b88\">sp_album_release</a> (<a class=\"el\" href=\"group__types.html#ga6fd3e5de729c429fef3ff18ece6dcfad\">sp_album</a> *album)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">const char *&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__artist.html#gad2895555bb48514986823733a7afe5e2\">sp_artist_name</a> (<a class=\"el\" href=\"group__types.html#ga31764fbd69618c10be173c6c03d4c1bc\">sp_artist</a> *artist)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">bool&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__artist.html#gafc98f5093184a7ac7ce608302b0971ea\">sp_artist_is_loaded</a> (<a class=\"el\" href=\"group__types.html#ga31764fbd69618c10be173c6c03d4c1bc\">sp_artist</a> *artist)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">const byte *&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__artist.html#ga87d366ac7479c717005c2c059d5f2be9\">sp_artist_portrait</a> (<a class=\"el\" href=\"group__types.html#ga31764fbd69618c10be173c6c03d4c1bc\">sp_artist</a> *artist, <a class=\"el\" href=\"group__session.html#ga61bc424465d776af3ceeb69eee2bb492\">sp_image_size</a> size)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__error.html#gafd27986ce4cd9eeaeca8adda83c9eb6b\">sp_error</a>&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__artist.html#gac70d7467f580aa497d1a5d610e06d273\">sp_artist_add_ref</a> (<a class=\"el\" href=\"group__types.html#ga31764fbd69618c10be173c6c03d4c1bc\">sp_artist</a> *artist)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__error.html#gafd27986ce4cd9eeaeca8adda83c9eb6b\">sp_error</a>&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__artist.html#ga7b0da8f7ce09454bd0821d06d52e2d12\">sp_artist_release</a> (<a class=\"el\" href=\"group__types.html#ga31764fbd69618c10be173c6c03d4c1bc\">sp_artist</a> *artist)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__types.html#ga9c4550473a7a07790778ba870c31b4d9\">sp_albumbrowse</a> *&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__albumbrowse.html#gaf1bc3042e748efea5ca7ac159e5cbfbe\">sp_albumbrowse_create</a> (<a class=\"el\" href=\"group__types.html#ga70dd19c6f824cf6a159575aa4c128b53\">sp_session</a> *session, <a class=\"el\" href=\"group__types.html#ga6fd3e5de729c429fef3ff18ece6dcfad\">sp_album</a> *album, <a class=\"el\" href=\"group__albumbrowse.html#gabd76254f89048e6d368929015a0c739f\">albumbrowse_complete_cb</a> *callback, void *userdata)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">bool&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__albumbrowse.html#gad618d2752eb55173ab373d1407971960\">sp_albumbrowse_is_loaded</a> (<a class=\"el\" href=\"group__types.html#ga9c4550473a7a07790778ba870c31b4d9\">sp_albumbrowse</a> *alb)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__error.html#gafd27986ce4cd9eeaeca8adda83c9eb6b\">sp_error</a>&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__albumbrowse.html#ga153417eee319e7711b66503f88fba88b\">sp_albumbrowse_error</a> (<a class=\"el\" href=\"group__types.html#ga9c4550473a7a07790778ba870c31b4d9\">sp_albumbrowse</a> *alb)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__types.html#ga6fd3e5de729c429fef3ff18ece6dcfad\">sp_album</a> *&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__albumbrowse.html#gaf0dadfc4edb48a3558b606e30e8bedfa\">sp_albumbrowse_album</a> (<a class=\"el\" href=\"group__types.html#ga9c4550473a7a07790778ba870c31b4d9\">sp_albumbrowse</a> *alb)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__types.html#ga31764fbd69618c10be173c6c03d4c1bc\">sp_artist</a> *&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__albumbrowse.html#ga4f835537a65bcac9ec52cef1058a44bc\">sp_albumbrowse_artist</a> (<a class=\"el\" href=\"group__types.html#ga9c4550473a7a07790778ba870c31b4d9\">sp_albumbrowse</a> *alb)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">int&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__albumbrowse.html#gab53fa74ee1958dad5186be09e70ddc4a\">sp_albumbrowse_num_copyrights</a> (<a class=\"el\" href=\"group__types.html#ga9c4550473a7a07790778ba870c31b4d9\">sp_albumbrowse</a> *alb)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">const char *&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__albumbrowse.html#ga34b205daa2960e8d02a6e1accd80ab92\">sp_albumbrowse_copyright</a> (<a class=\"el\" href=\"group__types.html#ga9c4550473a7a07790778ba870c31b4d9\">sp_albumbrowse</a> *alb, int index)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">int&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__albumbrowse.html#ga3fb91de745ca07d3801a57288f2d9da7\">sp_albumbrowse_num_tracks</a> (<a class=\"el\" href=\"group__types.html#ga9c4550473a7a07790778ba870c31b4d9\">sp_albumbrowse</a> *alb)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__types.html#ga47bbd2262f0c8b5d7147af7d62198e48\">sp_track</a> *&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__albumbrowse.html#gad3c8df4b75158bba2c06aaefa74c5aa1\">sp_albumbrowse_track</a> (<a class=\"el\" href=\"group__types.html#ga9c4550473a7a07790778ba870c31b4d9\">sp_albumbrowse</a> *alb, int index)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">const char *&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__albumbrowse.html#ga868f3f3263f5033ae1fba60f403be712\">sp_albumbrowse_review</a> (<a class=\"el\" href=\"group__types.html#ga9c4550473a7a07790778ba870c31b4d9\">sp_albumbrowse</a> *alb)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">int&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__albumbrowse.html#ga2f1e1049065e8c090c010f8e43061bd4\">sp_albumbrowse_backend_request_duration</a> (<a class=\"el\" href=\"group__types.html#ga9c4550473a7a07790778ba870c31b4d9\">sp_albumbrowse</a> *alb)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__error.html#gafd27986ce4cd9eeaeca8adda83c9eb6b\">sp_error</a>&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__albumbrowse.html#ga1afd6a10febf31a61cf356673cb34bef\">sp_albumbrowse_add_ref</a> (<a class=\"el\" href=\"group__types.html#ga9c4550473a7a07790778ba870c31b4d9\">sp_albumbrowse</a> *alb)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__error.html#gafd27986ce4cd9eeaeca8adda83c9eb6b\">sp_error</a>&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__albumbrowse.html#gabdd5a4e3b2098166b67e35979f59613d\">sp_albumbrowse_release</a> (<a class=\"el\" href=\"group__types.html#ga9c4550473a7a07790778ba870c31b4d9\">sp_albumbrowse</a> *alb)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__types.html#gafd3d5aae485f1012ec91b7948e6f9f2b\">sp_artistbrowse</a> *&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__artistbrowse.html#ga8dd8364b2fcd29c846209660bd9a69b2\">sp_artistbrowse_create</a> (<a class=\"el\" href=\"group__types.html#ga70dd19c6f824cf6a159575aa4c128b53\">sp_session</a> *session, <a class=\"el\" href=\"group__types.html#ga31764fbd69618c10be173c6c03d4c1bc\">sp_artist</a> *artist, <a class=\"el\" href=\"group__session.html#gac86504cc9e8cadbc30c8aa8dbf355034\">sp_artistbrowse_type</a> type, <a class=\"el\" href=\"group__artistbrowse.html#ga8077aa18c043210e859479be2616a3e7\">artistbrowse_complete_cb</a> *callback, void *userdata)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">bool&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__artistbrowse.html#ga966b0f59e7b2b3d0037e44bb49dcdabc\">sp_artistbrowse_is_loaded</a> (<a class=\"el\" href=\"group__types.html#gafd3d5aae485f1012ec91b7948e6f9f2b\">sp_artistbrowse</a> *arb)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__error.html#gafd27986ce4cd9eeaeca8adda83c9eb6b\">sp_error</a>&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__artistbrowse.html#ga203e757088ff7a5098f16a1367da25d2\">sp_artistbrowse_error</a> (<a class=\"el\" href=\"group__types.html#gafd3d5aae485f1012ec91b7948e6f9f2b\">sp_artistbrowse</a> *arb)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__types.html#ga31764fbd69618c10be173c6c03d4c1bc\">sp_artist</a> *&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__artistbrowse.html#ga5f6a046b2bd261d7628582b986a9019f\">sp_artistbrowse_artist</a> (<a class=\"el\" href=\"group__types.html#gafd3d5aae485f1012ec91b7948e6f9f2b\">sp_artistbrowse</a> *arb)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">int&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__artistbrowse.html#ga98dc47d36d2789999bfe62707c5041d7\">sp_artistbrowse_num_portraits</a> (<a class=\"el\" href=\"group__types.html#gafd3d5aae485f1012ec91b7948e6f9f2b\">sp_artistbrowse</a> *arb)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">const byte *&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__artistbrowse.html#ga5f164b2f9609a7bf2c89b3a1407ec239\">sp_artistbrowse_portrait</a> (<a class=\"el\" href=\"group__types.html#gafd3d5aae485f1012ec91b7948e6f9f2b\">sp_artistbrowse</a> *arb, int index)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">int&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__artistbrowse.html#ga8c862caa2234125ffcc4e93287b1e029\">sp_artistbrowse_num_tracks</a> (<a class=\"el\" href=\"group__types.html#gafd3d5aae485f1012ec91b7948e6f9f2b\">sp_artistbrowse</a> *arb)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__types.html#ga47bbd2262f0c8b5d7147af7d62198e48\">sp_track</a> *&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__artistbrowse.html#ga45d28771a856f935dc40ab40e27dec4c\">sp_artistbrowse_track</a> (<a class=\"el\" href=\"group__types.html#gafd3d5aae485f1012ec91b7948e6f9f2b\">sp_artistbrowse</a> *arb, int index)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">int&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__artistbrowse.html#ga0c26782796af954300ce92fddea97637\">sp_artistbrowse_num_tophit_tracks</a> (<a class=\"el\" href=\"group__types.html#gafd3d5aae485f1012ec91b7948e6f9f2b\">sp_artistbrowse</a> *arb)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__types.html#ga47bbd2262f0c8b5d7147af7d62198e48\">sp_track</a> *&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__artistbrowse.html#ga5da55f43def03fe9f0d2c8b252b9755a\">sp_artistbrowse_tophit_track</a> (<a class=\"el\" href=\"group__types.html#gafd3d5aae485f1012ec91b7948e6f9f2b\">sp_artistbrowse</a> *arb, int index)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">int&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__artistbrowse.html#gaf0055361abd53425d89a4636a32b5c83\">sp_artistbrowse_num_albums</a> (<a class=\"el\" href=\"group__types.html#gafd3d5aae485f1012ec91b7948e6f9f2b\">sp_artistbrowse</a> *arb)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__types.html#ga6fd3e5de729c429fef3ff18ece6dcfad\">sp_album</a> *&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__artistbrowse.html#ga5b36c9a34876beea8fda8674b93d4fd3\">sp_artistbrowse_album</a> (<a class=\"el\" href=\"group__types.html#gafd3d5aae485f1012ec91b7948e6f9f2b\">sp_artistbrowse</a> *arb, int index)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">int&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__artistbrowse.html#ga2559638742416ac621af0e919e017d17\">sp_artistbrowse_num_similar_artists</a> (<a class=\"el\" href=\"group__types.html#gafd3d5aae485f1012ec91b7948e6f9f2b\">sp_artistbrowse</a> *arb)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__types.html#ga31764fbd69618c10be173c6c03d4c1bc\">sp_artist</a> *&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__artistbrowse.html#gac60ef4f9e006a920f1d72b6098743fbc\">sp_artistbrowse_similar_artist</a> (<a class=\"el\" href=\"group__types.html#gafd3d5aae485f1012ec91b7948e6f9f2b\">sp_artistbrowse</a> *arb, int index)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">const char *&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__artistbrowse.html#ga8b93b9e5630662855f35694280ba4d2b\">sp_artistbrowse_biography</a> (<a class=\"el\" href=\"group__types.html#gafd3d5aae485f1012ec91b7948e6f9f2b\">sp_artistbrowse</a> *arb)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">int&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__artistbrowse.html#gadce357748b82abce8a7b093882850fdb\">sp_artistbrowse_backend_request_duration</a> (<a class=\"el\" href=\"group__types.html#gafd3d5aae485f1012ec91b7948e6f9f2b\">sp_artistbrowse</a> *arb)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__error.html#gafd27986ce4cd9eeaeca8adda83c9eb6b\">sp_error</a>&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__artistbrowse.html#ga69fc2e1d2d5e8d91a724486cbfd0c4dc\">sp_artistbrowse_add_ref</a> (<a class=\"el\" href=\"group__types.html#gafd3d5aae485f1012ec91b7948e6f9f2b\">sp_artistbrowse</a> *arb)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__error.html#gafd27986ce4cd9eeaeca8adda83c9eb6b\">sp_error</a>&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__artistbrowse.html#ga14626a4f6a60b1caf61cb54c26783671\">sp_artistbrowse_release</a> (<a class=\"el\" href=\"group__types.html#gafd3d5aae485f1012ec91b7948e6f9f2b\">sp_artistbrowse</a> *arb)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__types.html#ga61155ca7b1ba941e15490e417441917b\">sp_image</a> *&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__image.html#gaf29e89f45945db2b3667bf9db4279c33\">sp_image_create</a> (<a class=\"el\" href=\"group__types.html#ga70dd19c6f824cf6a159575aa4c128b53\">sp_session</a> *session, const byte image_id[20])</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__types.html#ga61155ca7b1ba941e15490e417441917b\">sp_image</a> *&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__image.html#ga70fb25cd2b0caaf15f637f36e75524b9\">sp_image_create_from_link</a> (<a class=\"el\" href=\"group__types.html#ga70dd19c6f824cf6a159575aa4c128b53\">sp_session</a> *session, <a class=\"el\" href=\"group__types.html#gaf90a23d6b662c96d52ac19f7f4bc1e39\">sp_link</a> *l)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__error.html#gafd27986ce4cd9eeaeca8adda83c9eb6b\">sp_error</a>&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__image.html#gaa414f26ad1b9095645a83361597c92ce\">sp_image_add_load_callback</a> (<a class=\"el\" href=\"group__types.html#ga61155ca7b1ba941e15490e417441917b\">sp_image</a> *image, <a class=\"el\" href=\"group__image.html#ga713bef7c5dedba7d91b9710cd9b5faa4\">image_loaded_cb</a> *callback, void *userdata)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__error.html#gafd27986ce4cd9eeaeca8adda83c9eb6b\">sp_error</a>&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__image.html#gaaee68c65d9eab3499f2b6be5d048d6ba\">sp_image_remove_load_callback</a> (<a class=\"el\" href=\"group__types.html#ga61155ca7b1ba941e15490e417441917b\">sp_image</a> *image, <a class=\"el\" href=\"group__image.html#ga713bef7c5dedba7d91b9710cd9b5faa4\">image_loaded_cb</a> *callback, void *userdata)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">bool&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__image.html#ga45312b1b9b5e5565485d61a8f0300e18\">sp_image_is_loaded</a> (<a class=\"el\" href=\"group__types.html#ga61155ca7b1ba941e15490e417441917b\">sp_image</a> *image)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__error.html#gafd27986ce4cd9eeaeca8adda83c9eb6b\">sp_error</a>&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__image.html#gae40103df87426b346e0d0413d8d3b0ff\">sp_image_error</a> (<a class=\"el\" href=\"group__types.html#ga61155ca7b1ba941e15490e417441917b\">sp_image</a> *image)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__image.html#ga2cda19baf2460da5e81fb1917f54626b\">sp_imageformat</a>&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__image.html#ga04448e81ca4916ba7ed223d0d817e803\">sp_image_format</a> (<a class=\"el\" href=\"group__types.html#ga61155ca7b1ba941e15490e417441917b\">sp_image</a> *image)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">const void *&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__image.html#ga03700a7dfa90bfc8200b89f15acd91aa\">sp_image_data</a> (<a class=\"el\" href=\"group__types.html#ga61155ca7b1ba941e15490e417441917b\">sp_image</a> *image, size_t *data_size)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">const byte *&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__image.html#ga0ee0b98cc25c995fe208a992cc87d145\">sp_image_image_id</a> (<a class=\"el\" href=\"group__types.html#ga61155ca7b1ba941e15490e417441917b\">sp_image</a> *image)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__error.html#gafd27986ce4cd9eeaeca8adda83c9eb6b\">sp_error</a>&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__image.html#ga98c93dbedfb182243742131a5224b83b\">sp_image_add_ref</a> (<a class=\"el\" href=\"group__types.html#ga61155ca7b1ba941e15490e417441917b\">sp_image</a> *image)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__error.html#gafd27986ce4cd9eeaeca8adda83c9eb6b\">sp_error</a>&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__image.html#ga3df9af5f68b18df5a598b7510e9b587f\">sp_image_release</a> (<a class=\"el\" href=\"group__types.html#ga61155ca7b1ba941e15490e417441917b\">sp_image</a> *image)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__types.html#gac95893a6b23d4b19f6f149eed6ead1fd\">sp_search</a> *&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__search.html#ga2f64dfbcc1313e7d5179998cb28208d4\">sp_search_create</a> (<a class=\"el\" href=\"group__types.html#ga70dd19c6f824cf6a159575aa4c128b53\">sp_session</a> *session, const char *query, int track_offset, int track_count, int album_offset, int album_count, int artist_offset, int artist_count, int playlist_offset, int playlist_count, <a class=\"el\" href=\"group__session.html#ga99e8e9176ce40fff08a9be8b944edb09\">sp_search_type</a> search_type, <a class=\"el\" href=\"group__search.html#gabcd51c99a318b9f36dfe2948d8209bb1\">search_complete_cb</a> *callback, void *userdata)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">bool&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__search.html#ga70e8c404d8c7ce0bbef70c2b274417cd\">sp_search_is_loaded</a> (<a class=\"el\" href=\"group__types.html#gac95893a6b23d4b19f6f149eed6ead1fd\">sp_search</a> *search)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__error.html#gafd27986ce4cd9eeaeca8adda83c9eb6b\">sp_error</a>&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__search.html#ga7cf655e37a823f952d30270d4fb60f10\">sp_search_error</a> (<a class=\"el\" href=\"group__types.html#gac95893a6b23d4b19f6f149eed6ead1fd\">sp_search</a> *search)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">int&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__search.html#ga1dd18cf7b3b3b7f4bf6e92a2140378d0\">sp_search_num_tracks</a> (<a class=\"el\" href=\"group__types.html#gac95893a6b23d4b19f6f149eed6ead1fd\">sp_search</a> *search)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__types.html#ga47bbd2262f0c8b5d7147af7d62198e48\">sp_track</a> *&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__search.html#gae9da7ca59ce0bbd73f7bcef4e15c4da8\">sp_search_track</a> (<a class=\"el\" href=\"group__types.html#gac95893a6b23d4b19f6f149eed6ead1fd\">sp_search</a> *search, int index)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">int&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__search.html#ga0c456a6396c4c05fbc8677ea641ef1f7\">sp_search_num_albums</a> (<a class=\"el\" href=\"group__types.html#gac95893a6b23d4b19f6f149eed6ead1fd\">sp_search</a> *search)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__types.html#ga6fd3e5de729c429fef3ff18ece6dcfad\">sp_album</a> *&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__search.html#ga4ba7723e70db0c6a4569c4bcd44f0e98\">sp_search_album</a> (<a class=\"el\" href=\"group__types.html#gac95893a6b23d4b19f6f149eed6ead1fd\">sp_search</a> *search, int index)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">int&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__search.html#gaa9f007f439d8241bf632f9abb8d926c9\">sp_search_num_playlists</a> (<a class=\"el\" href=\"group__types.html#gac95893a6b23d4b19f6f149eed6ead1fd\">sp_search</a> *search)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__types.html#ga1bcf54cbc117a20ab2c15e59eb3a8174\">sp_playlist</a> *&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__search.html#ga4175fba17f355b1c0bd361357181ea35\">sp_search_playlist</a> (<a class=\"el\" href=\"group__types.html#gac95893a6b23d4b19f6f149eed6ead1fd\">sp_search</a> *search, int index)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">const char *&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__search.html#ga933cd5d5a0ccca9906082ca4549a4ed7\">sp_search_playlist_name</a> (<a class=\"el\" href=\"group__types.html#gac95893a6b23d4b19f6f149eed6ead1fd\">sp_search</a> *search, int index)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">const char *&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__search.html#ga0071a3d30f0f0c4e477bf923e9014ff5\">sp_search_playlist_uri</a> (<a class=\"el\" href=\"group__types.html#gac95893a6b23d4b19f6f149eed6ead1fd\">sp_search</a> *search, int index)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">const char *&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__search.html#gac4463fab4ea25e0a5d5079c959a1781c\">sp_search_playlist_image_uri</a> (<a class=\"el\" href=\"group__types.html#gac95893a6b23d4b19f6f149eed6ead1fd\">sp_search</a> *search, int index)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">int&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__search.html#gabd375a613c2dadecad8c13f8aca6f2d3\">sp_search_num_artists</a> (<a class=\"el\" href=\"group__types.html#gac95893a6b23d4b19f6f149eed6ead1fd\">sp_search</a> *search)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__types.html#ga31764fbd69618c10be173c6c03d4c1bc\">sp_artist</a> *&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__search.html#ga79b3d532d5a20a3b2bf2a087eead7888\">sp_search_artist</a> (<a class=\"el\" href=\"group__types.html#gac95893a6b23d4b19f6f149eed6ead1fd\">sp_search</a> *search, int index)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">const char *&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__search.html#ga127e9c2bf98e3602ecfc2926b9d242bf\">sp_search_query</a> (<a class=\"el\" href=\"group__types.html#gac95893a6b23d4b19f6f149eed6ead1fd\">sp_search</a> *search)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">const char *&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__search.html#ga8561c1da8b93ecdc8f2d325a9d19199b\">sp_search_did_you_mean</a> (<a class=\"el\" href=\"group__types.html#gac95893a6b23d4b19f6f149eed6ead1fd\">sp_search</a> *search)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">int&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__search.html#gab4e50582c517b4639fd1afd6fb011587\">sp_search_total_tracks</a> (<a class=\"el\" href=\"group__types.html#gac95893a6b23d4b19f6f149eed6ead1fd\">sp_search</a> *search)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">int&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__search.html#gaafd3b228adbc028937383d0d45730581\">sp_search_total_albums</a> (<a class=\"el\" href=\"group__types.html#gac95893a6b23d4b19f6f149eed6ead1fd\">sp_search</a> *search)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">int&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__search.html#ga305a4118625e0f70cfb14161a0112fd5\">sp_search_total_artists</a> (<a class=\"el\" href=\"group__types.html#gac95893a6b23d4b19f6f149eed6ead1fd\">sp_search</a> *search)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">int&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__search.html#ga2e286415a6ba8dbf85ea677906f2798c\">sp_search_total_playlists</a> (<a class=\"el\" href=\"group__types.html#gac95893a6b23d4b19f6f149eed6ead1fd\">sp_search</a> *search)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__error.html#gafd27986ce4cd9eeaeca8adda83c9eb6b\">sp_error</a>&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__search.html#ga92e45a5edb1e33e64fdb857bd8eb9ad5\">sp_search_add_ref</a> (<a class=\"el\" href=\"group__types.html#gac95893a6b23d4b19f6f149eed6ead1fd\">sp_search</a> *search)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__error.html#gafd27986ce4cd9eeaeca8adda83c9eb6b\">sp_error</a>&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__search.html#ga4e01d43067d9f8c533c985f90143821b\">sp_search_release</a> (<a class=\"el\" href=\"group__types.html#gac95893a6b23d4b19f6f149eed6ead1fd\">sp_search</a> *search)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">bool&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__playlist.html#gaee8ea6c07dfdca3397e27b278fa4870a\">sp_playlist_is_loaded</a> (<a class=\"el\" href=\"group__types.html#ga1bcf54cbc117a20ab2c15e59eb3a8174\">sp_playlist</a> *playlist)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__error.html#gafd27986ce4cd9eeaeca8adda83c9eb6b\">sp_error</a>&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__playlist.html#gab15fca12d387c69b4998a4d2b48e5b32\">sp_playlist_add_callbacks</a> (<a class=\"el\" href=\"group__types.html#ga1bcf54cbc117a20ab2c15e59eb3a8174\">sp_playlist</a> *playlist, <a class=\"el\" href=\"structsp__playlist__callbacks.html\">sp_playlist_callbacks</a> *callbacks, void *userdata)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__error.html#gafd27986ce4cd9eeaeca8adda83c9eb6b\">sp_error</a>&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__playlist.html#ga7fcbf909a0fa8bf25f0b1d1e7dd0e160\">sp_playlist_remove_callbacks</a> (<a class=\"el\" href=\"group__types.html#ga1bcf54cbc117a20ab2c15e59eb3a8174\">sp_playlist</a> *playlist, <a class=\"el\" href=\"structsp__playlist__callbacks.html\">sp_playlist_callbacks</a> *callbacks, void *userdata)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">int&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__playlist.html#ga684a3acc60f99b3b26488ed813ee5d23\">sp_playlist_num_tracks</a> (<a class=\"el\" href=\"group__types.html#ga1bcf54cbc117a20ab2c15e59eb3a8174\">sp_playlist</a> *playlist)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__types.html#ga47bbd2262f0c8b5d7147af7d62198e48\">sp_track</a> *&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__playlist.html#ga7a03854fe6072476306780d23c6cac16\">sp_playlist_track</a> (<a class=\"el\" href=\"group__types.html#ga1bcf54cbc117a20ab2c15e59eb3a8174\">sp_playlist</a> *playlist, int index)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">int&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__playlist.html#gab8e77f8d63e787f8aa1a066d74daa74c\">sp_playlist_track_create_time</a> (<a class=\"el\" href=\"group__types.html#ga1bcf54cbc117a20ab2c15e59eb3a8174\">sp_playlist</a> *playlist, int index)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__types.html#gaed2dbaa1eebd6752f76613daad9158bc\">sp_user</a> *&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__playlist.html#ga80fcd9e7b40c791433c07d66e2ad432a\">sp_playlist_track_creator</a> (<a class=\"el\" href=\"group__types.html#ga1bcf54cbc117a20ab2c15e59eb3a8174\">sp_playlist</a> *playlist, int index)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">bool&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__playlist.html#gab9e00ee5bc6b5dc0b3d58cbdb32c0c7b\">sp_playlist_track_seen</a> (<a class=\"el\" href=\"group__types.html#ga1bcf54cbc117a20ab2c15e59eb3a8174\">sp_playlist</a> *playlist, int index)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__error.html#gafd27986ce4cd9eeaeca8adda83c9eb6b\">sp_error</a>&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__playlist.html#ga69f5cc1bdd7dbdcdb476a7b1d2b7834d\">sp_playlist_track_set_seen</a> (<a class=\"el\" href=\"group__types.html#ga1bcf54cbc117a20ab2c15e59eb3a8174\">sp_playlist</a> *playlist, int index, bool seen)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">const char *&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__playlist.html#ga6887b9dabb30a060b10bdb75f8b3f971\">sp_playlist_track_message</a> (<a class=\"el\" href=\"group__types.html#ga1bcf54cbc117a20ab2c15e59eb3a8174\">sp_playlist</a> *playlist, int index)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">const char *&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__playlist.html#ga61b7e33cc1aedb4e31a2af75ae0ac8cc\">sp_playlist_name</a> (<a class=\"el\" href=\"group__types.html#ga1bcf54cbc117a20ab2c15e59eb3a8174\">sp_playlist</a> *playlist)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__error.html#gafd27986ce4cd9eeaeca8adda83c9eb6b\">sp_error</a>&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__playlist.html#gad6c3880c514353e204fdd90830b516ec\">sp_playlist_rename</a> (<a class=\"el\" href=\"group__types.html#ga1bcf54cbc117a20ab2c15e59eb3a8174\">sp_playlist</a> *playlist, const char *new_name)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__types.html#gaed2dbaa1eebd6752f76613daad9158bc\">sp_user</a> *&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__playlist.html#gac3e4295d3353eb9998402aedfdbd55de\">sp_playlist_owner</a> (<a class=\"el\" href=\"group__types.html#ga1bcf54cbc117a20ab2c15e59eb3a8174\">sp_playlist</a> *playlist)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">bool&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__playlist.html#ga8ad160f654f02f13690568070dd57353\">sp_playlist_is_collaborative</a> (<a class=\"el\" href=\"group__types.html#ga1bcf54cbc117a20ab2c15e59eb3a8174\">sp_playlist</a> *playlist)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__error.html#gafd27986ce4cd9eeaeca8adda83c9eb6b\">sp_error</a>&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__playlist.html#gad15410bcc2ebd986adabda865830bce4\">sp_playlist_set_collaborative</a> (<a class=\"el\" href=\"group__types.html#ga1bcf54cbc117a20ab2c15e59eb3a8174\">sp_playlist</a> *playlist, bool collaborative)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__error.html#gafd27986ce4cd9eeaeca8adda83c9eb6b\">sp_error</a>&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__playlist.html#ga0bde47f340e0cd590a78007c6af69307\">sp_playlist_set_autolink_tracks</a> (<a class=\"el\" href=\"group__types.html#ga1bcf54cbc117a20ab2c15e59eb3a8174\">sp_playlist</a> *playlist, bool link)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">const char *&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__playlist.html#gab1d8e0ee9b436ecbb104bbd6cc0665be\">sp_playlist_get_description</a> (<a class=\"el\" href=\"group__types.html#ga1bcf54cbc117a20ab2c15e59eb3a8174\">sp_playlist</a> *playlist)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">bool&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__playlist.html#ga409cb6b2a88db7242ec939b6644e8c30\">sp_playlist_get_image</a> (<a class=\"el\" href=\"group__types.html#ga1bcf54cbc117a20ab2c15e59eb3a8174\">sp_playlist</a> *playlist, byte image[20])</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">bool&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__playlist.html#gaf0e39b5969259d10625eb398af0f3f43\">sp_playlist_has_pending_changes</a> (<a class=\"el\" href=\"group__types.html#ga1bcf54cbc117a20ab2c15e59eb3a8174\">sp_playlist</a> *playlist)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__error.html#gafd27986ce4cd9eeaeca8adda83c9eb6b\">sp_error</a>&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__playlist.html#ga2344a47133f7f0aed0a67e154ecc4dc4\">sp_playlist_add_tracks</a> (<a class=\"el\" href=\"group__types.html#ga1bcf54cbc117a20ab2c15e59eb3a8174\">sp_playlist</a> *playlist, <a class=\"el\" href=\"group__types.html#ga47bbd2262f0c8b5d7147af7d62198e48\">sp_track</a> *const *tracks, int num_tracks, int position, <a class=\"el\" href=\"group__types.html#ga70dd19c6f824cf6a159575aa4c128b53\">sp_session</a> *session)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__error.html#gafd27986ce4cd9eeaeca8adda83c9eb6b\">sp_error</a>&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__playlist.html#gabd62cd7ff9484b4c31ff7f159ec41b6a\">sp_playlist_remove_tracks</a> (<a class=\"el\" href=\"group__types.html#ga1bcf54cbc117a20ab2c15e59eb3a8174\">sp_playlist</a> *playlist, const int *tracks, int num_tracks)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__error.html#gafd27986ce4cd9eeaeca8adda83c9eb6b\">sp_error</a>&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__playlist.html#ga90ffd8c9fc6abc7375e89f4cb49adb11\">sp_playlist_reorder_tracks</a> (<a class=\"el\" href=\"group__types.html#ga1bcf54cbc117a20ab2c15e59eb3a8174\">sp_playlist</a> *playlist, const int *tracks, int num_tracks, int new_position)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">unsigned int&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__playlist.html#ga967ad87f0db702513ecda82546f667c5\">sp_playlist_num_subscribers</a> (<a class=\"el\" href=\"group__types.html#ga1bcf54cbc117a20ab2c15e59eb3a8174\">sp_playlist</a> *playlist)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"structsp__subscribers.html\">sp_subscribers</a> *&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__playlist.html#gad49f491babc475f8d4aeea1b4452ff8b\">sp_playlist_subscribers</a> (<a class=\"el\" href=\"group__types.html#ga1bcf54cbc117a20ab2c15e59eb3a8174\">sp_playlist</a> *playlist)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__error.html#gafd27986ce4cd9eeaeca8adda83c9eb6b\">sp_error</a>&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__playlist.html#gae7754b74b1c3c8f5222ca43b6608ce6a\">sp_playlist_subscribers_free</a> (<a class=\"el\" href=\"structsp__subscribers.html\">sp_subscribers</a> *subscribers)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__error.html#gafd27986ce4cd9eeaeca8adda83c9eb6b\">sp_error</a>&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__playlist.html#ga9ebbf147230b3ca98b68e556cf24e6bd\">sp_playlist_update_subscribers</a> (<a class=\"el\" href=\"group__types.html#ga70dd19c6f824cf6a159575aa4c128b53\">sp_session</a> *session, <a class=\"el\" href=\"group__types.html#ga1bcf54cbc117a20ab2c15e59eb3a8174\">sp_playlist</a> *playlist)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">bool&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__playlist.html#ga28456d1242693c6d890516dc782ab3ec\">sp_playlist_is_in_ram</a> (<a class=\"el\" href=\"group__types.html#ga70dd19c6f824cf6a159575aa4c128b53\">sp_session</a> *session, <a class=\"el\" href=\"group__types.html#ga1bcf54cbc117a20ab2c15e59eb3a8174\">sp_playlist</a> *playlist)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__error.html#gafd27986ce4cd9eeaeca8adda83c9eb6b\">sp_error</a>&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__playlist.html#gaf6ca8a349bdd982f6c8dda52ed691017\">sp_playlist_set_in_ram</a> (<a class=\"el\" href=\"group__types.html#ga70dd19c6f824cf6a159575aa4c128b53\">sp_session</a> *session, <a class=\"el\" href=\"group__types.html#ga1bcf54cbc117a20ab2c15e59eb3a8174\">sp_playlist</a> *playlist, bool in_ram)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__types.html#ga1bcf54cbc117a20ab2c15e59eb3a8174\">sp_playlist</a> *&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__playlist.html#ga342a6a0cfe10531ef7cb3c6629c1e8e7\">sp_playlist_create</a> (<a class=\"el\" href=\"group__types.html#ga70dd19c6f824cf6a159575aa4c128b53\">sp_session</a> *session, <a class=\"el\" href=\"group__types.html#gaf90a23d6b662c96d52ac19f7f4bc1e39\">sp_link</a> *link)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__error.html#gafd27986ce4cd9eeaeca8adda83c9eb6b\">sp_error</a>&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__playlist.html#ga784f648f9cc431ef3b51f3491c2f169f\">sp_playlist_set_offline_mode</a> (<a class=\"el\" href=\"group__types.html#ga70dd19c6f824cf6a159575aa4c128b53\">sp_session</a> *session, <a class=\"el\" href=\"group__types.html#ga1bcf54cbc117a20ab2c15e59eb3a8174\">sp_playlist</a> *playlist, bool offline)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__session.html#ga811fa52ed0fdb5cda732682e27e40417\">sp_playlist_offline_status</a>&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__playlist.html#ga7170157af21445c37a21a2241f91ff06\">sp_playlist_get_offline_status</a> (<a class=\"el\" href=\"group__types.html#ga70dd19c6f824cf6a159575aa4c128b53\">sp_session</a> *session, <a class=\"el\" href=\"group__types.html#ga1bcf54cbc117a20ab2c15e59eb3a8174\">sp_playlist</a> *playlist)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">int&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__playlist.html#ga83ca1a25f50834f8e6f8ee1e883a8c6e\">sp_playlist_get_offline_download_completed</a> (<a class=\"el\" href=\"group__types.html#ga70dd19c6f824cf6a159575aa4c128b53\">sp_session</a> *session, <a class=\"el\" href=\"group__types.html#ga1bcf54cbc117a20ab2c15e59eb3a8174\">sp_playlist</a> *playlist)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__error.html#gafd27986ce4cd9eeaeca8adda83c9eb6b\">sp_error</a>&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__playlist.html#gacb10979add5a954e5c1600ef9c5b17a8\">sp_playlist_add_ref</a> (<a class=\"el\" href=\"group__types.html#ga1bcf54cbc117a20ab2c15e59eb3a8174\">sp_playlist</a> *playlist)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__error.html#gafd27986ce4cd9eeaeca8adda83c9eb6b\">sp_error</a>&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__playlist.html#gacb9250eb530869b039541a8b62dfab6c\">sp_playlist_release</a> (<a class=\"el\" href=\"group__types.html#ga1bcf54cbc117a20ab2c15e59eb3a8174\">sp_playlist</a> *playlist)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__error.html#gafd27986ce4cd9eeaeca8adda83c9eb6b\">sp_error</a>&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__playlist.html#ga1976cb49c391cdd2dbe7c40d1bc71570\">sp_playlistcontainer_add_callbacks</a> (<a class=\"el\" href=\"group__types.html#ga45a2febbe167483e48dab8d606d462d7\">sp_playlistcontainer</a> *pc, <a class=\"el\" href=\"structsp__playlistcontainer__callbacks.html\">sp_playlistcontainer_callbacks</a> *callbacks, void *userdata)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__error.html#gafd27986ce4cd9eeaeca8adda83c9eb6b\">sp_error</a>&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__playlist.html#gafb5242b8f0f9964cec29d32f4d6c1164\">sp_playlistcontainer_remove_callbacks</a> (<a class=\"el\" href=\"group__types.html#ga45a2febbe167483e48dab8d606d462d7\">sp_playlistcontainer</a> *pc, <a class=\"el\" href=\"structsp__playlistcontainer__callbacks.html\">sp_playlistcontainer_callbacks</a> *callbacks, void *userdata)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">int&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__playlist.html#ga7a1cbf558b2b364b8249d4ce432df700\">sp_playlistcontainer_num_playlists</a> (<a class=\"el\" href=\"group__types.html#ga45a2febbe167483e48dab8d606d462d7\">sp_playlistcontainer</a> *pc)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">bool&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__playlist.html#gae23cb67b4b26bca663034997c4418fa8\">sp_playlistcontainer_is_loaded</a> (<a class=\"el\" href=\"group__types.html#ga45a2febbe167483e48dab8d606d462d7\">sp_playlistcontainer</a> *pc)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__types.html#ga1bcf54cbc117a20ab2c15e59eb3a8174\">sp_playlist</a> *&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__playlist.html#ga5ddd8c8064c281a14c6fd7877f522dc6\">sp_playlistcontainer_playlist</a> (<a class=\"el\" href=\"group__types.html#ga45a2febbe167483e48dab8d606d462d7\">sp_playlistcontainer</a> *pc, int index)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__session.html#gafdd7117213605e6f2671c4f289b44609\">sp_playlist_type</a>&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__playlist.html#ga79286860a3eeada495e97c5ad1fd7ebf\">sp_playlistcontainer_playlist_type</a> (<a class=\"el\" href=\"group__types.html#ga45a2febbe167483e48dab8d606d462d7\">sp_playlistcontainer</a> *pc, int index)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__error.html#gafd27986ce4cd9eeaeca8adda83c9eb6b\">sp_error</a>&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__playlist.html#ga852e5f5bcd4520be2e3d6d5d94def44a\">sp_playlistcontainer_playlist_folder_name</a> (<a class=\"el\" href=\"group__types.html#ga45a2febbe167483e48dab8d606d462d7\">sp_playlistcontainer</a> *pc, int index, char *buffer, int buffer_size)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">sp_uint64&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__playlist.html#ga6939f9db71199612fc5a19d395e3a7f8\">sp_playlistcontainer_playlist_folder_id</a> (<a class=\"el\" href=\"group__types.html#ga45a2febbe167483e48dab8d606d462d7\">sp_playlistcontainer</a> *pc, int index)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__types.html#ga1bcf54cbc117a20ab2c15e59eb3a8174\">sp_playlist</a> *&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__playlist.html#ga840b82b1074a7ca1c9eacd351bed24c2\">sp_playlistcontainer_add_new_playlist</a> (<a class=\"el\" href=\"group__types.html#ga45a2febbe167483e48dab8d606d462d7\">sp_playlistcontainer</a> *pc, const char *name)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__types.html#ga1bcf54cbc117a20ab2c15e59eb3a8174\">sp_playlist</a> *&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__playlist.html#ga87699479087915b741ceef4eebe69ad8\">sp_playlistcontainer_add_playlist</a> (<a class=\"el\" href=\"group__types.html#ga45a2febbe167483e48dab8d606d462d7\">sp_playlistcontainer</a> *pc, <a class=\"el\" href=\"group__types.html#gaf90a23d6b662c96d52ac19f7f4bc1e39\">sp_link</a> *link)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__error.html#gafd27986ce4cd9eeaeca8adda83c9eb6b\">sp_error</a>&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__playlist.html#ga1ae1d51c4305940ae5c5c98c12be0afc\">sp_playlistcontainer_remove_playlist</a> (<a class=\"el\" href=\"group__types.html#ga45a2febbe167483e48dab8d606d462d7\">sp_playlistcontainer</a> *pc, int index)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__error.html#gafd27986ce4cd9eeaeca8adda83c9eb6b\">sp_error</a>&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__playlist.html#gad9be708159957d4c1e5ef905550808c5\">sp_playlistcontainer_move_playlist</a> (<a class=\"el\" href=\"group__types.html#ga45a2febbe167483e48dab8d606d462d7\">sp_playlistcontainer</a> *pc, int index, int new_position, bool dry_run)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__error.html#gafd27986ce4cd9eeaeca8adda83c9eb6b\">sp_error</a>&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__playlist.html#ga0862502eea52fc5f2465ebad6fd98796\">sp_playlistcontainer_add_folder</a> (<a class=\"el\" href=\"group__types.html#ga45a2febbe167483e48dab8d606d462d7\">sp_playlistcontainer</a> *pc, int index, const char *name)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__types.html#gaed2dbaa1eebd6752f76613daad9158bc\">sp_user</a> *&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__playlist.html#gad4fc67d1386dd637f778f4e735a36894\">sp_playlistcontainer_owner</a> (<a class=\"el\" href=\"group__types.html#ga45a2febbe167483e48dab8d606d462d7\">sp_playlistcontainer</a> *pc)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__error.html#gafd27986ce4cd9eeaeca8adda83c9eb6b\">sp_error</a>&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__playlist.html#ga2138c537a6ebcd35a01eea54d0dd1e8f\">sp_playlistcontainer_add_ref</a> (<a class=\"el\" href=\"group__types.html#ga45a2febbe167483e48dab8d606d462d7\">sp_playlistcontainer</a> *pc)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__error.html#gafd27986ce4cd9eeaeca8adda83c9eb6b\">sp_error</a>&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__playlist.html#ga0311c7c3c4f26028e5edd4aacb36dbf8\">sp_playlistcontainer_release</a> (<a class=\"el\" href=\"group__types.html#ga45a2febbe167483e48dab8d606d462d7\">sp_playlistcontainer</a> *pc)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">int&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__playlist.html#gad9e11b45843ee4a147b43038a2e55f13\">sp_playlistcontainer_get_unseen_tracks</a> (<a class=\"el\" href=\"group__types.html#ga45a2febbe167483e48dab8d606d462d7\">sp_playlistcontainer</a> *pc, <a class=\"el\" href=\"group__types.html#ga1bcf54cbc117a20ab2c15e59eb3a8174\">sp_playlist</a> *playlist, <a class=\"el\" href=\"group__types.html#ga47bbd2262f0c8b5d7147af7d62198e48\">sp_track</a> **tracks, int num_tracks)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">int&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__playlist.html#gadaad604c35e543363e1dd5b23c462db0\">sp_playlistcontainer_clear_unseen_tracks</a> (<a class=\"el\" href=\"group__types.html#ga45a2febbe167483e48dab8d606d462d7\">sp_playlistcontainer</a> *pc, <a class=\"el\" href=\"group__types.html#ga1bcf54cbc117a20ab2c15e59eb3a8174\">sp_playlist</a> *playlist)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">const char *&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__user.html#gad9ac5456cd129c31d2c577ba14e88f8c\">sp_user_canonical_name</a> (<a class=\"el\" href=\"group__types.html#gaed2dbaa1eebd6752f76613daad9158bc\">sp_user</a> *user)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">const char *&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__user.html#ga0052befb81a93bb7106ca863de892610\">sp_user_display_name</a> (<a class=\"el\" href=\"group__types.html#gaed2dbaa1eebd6752f76613daad9158bc\">sp_user</a> *user)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">bool&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__user.html#ga0996fb9814564e4ad39b8a500cb3de21\">sp_user_is_loaded</a> (<a class=\"el\" href=\"group__types.html#gaed2dbaa1eebd6752f76613daad9158bc\">sp_user</a> *user)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__error.html#gafd27986ce4cd9eeaeca8adda83c9eb6b\">sp_error</a>&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__user.html#ga232816a3c8f42ef2663b8d99261f2dae\">sp_user_add_ref</a> (<a class=\"el\" href=\"group__types.html#gaed2dbaa1eebd6752f76613daad9158bc\">sp_user</a> *user)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__error.html#gafd27986ce4cd9eeaeca8adda83c9eb6b\">sp_error</a>&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__user.html#gab1ffba4355073e1f72594c9e1b22ebb4\">sp_user_release</a> (<a class=\"el\" href=\"group__types.html#gaed2dbaa1eebd6752f76613daad9158bc\">sp_user</a> *user)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__types.html#ga723de429cd073bcf5d13fb4e0f466ffd\">sp_toplistbrowse</a> *&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__toplist.html#gac2fe366e0050747438e09cdd22ed0e31\">sp_toplistbrowse_create</a> (<a class=\"el\" href=\"group__types.html#ga70dd19c6f824cf6a159575aa4c128b53\">sp_session</a> *session, <a class=\"el\" href=\"group__toplist.html#ga220f32522efb2828e4f8ffb949af234a\">sp_toplisttype</a> type, <a class=\"el\" href=\"group__toplist.html#ga6fa5cfed2cbb33f2f64542d0b63f6c8d\">sp_toplistregion</a> region, const char *username, <a class=\"el\" href=\"group__toplist.html#gafe8e94ae23133105f35c03b9e3836a0a\">toplistbrowse_complete_cb</a> *callback, void *userdata)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">bool&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__toplist.html#gaff81156c09d311c4f6a82d28a32d7968\">sp_toplistbrowse_is_loaded</a> (<a class=\"el\" href=\"group__types.html#ga723de429cd073bcf5d13fb4e0f466ffd\">sp_toplistbrowse</a> *tlb)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__error.html#gafd27986ce4cd9eeaeca8adda83c9eb6b\">sp_error</a>&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__toplist.html#ga9b881929e74d97f64814ae54953ce4d7\">sp_toplistbrowse_error</a> (<a class=\"el\" href=\"group__types.html#ga723de429cd073bcf5d13fb4e0f466ffd\">sp_toplistbrowse</a> *tlb)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__error.html#gafd27986ce4cd9eeaeca8adda83c9eb6b\">sp_error</a>&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__toplist.html#ga421a19f128e5f3ae4b36e63a133a2a83\">sp_toplistbrowse_add_ref</a> (<a class=\"el\" href=\"group__types.html#ga723de429cd073bcf5d13fb4e0f466ffd\">sp_toplistbrowse</a> *tlb)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__error.html#gafd27986ce4cd9eeaeca8adda83c9eb6b\">sp_error</a>&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__toplist.html#gac6cf969c9cb6b431aeaa4723820ca8de\">sp_toplistbrowse_release</a> (<a class=\"el\" href=\"group__types.html#ga723de429cd073bcf5d13fb4e0f466ffd\">sp_toplistbrowse</a> *tlb)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">int&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__toplist.html#gae2f5c09fbbf947834b1b1e73461f1fb3\">sp_toplistbrowse_num_artists</a> (<a class=\"el\" href=\"group__types.html#ga723de429cd073bcf5d13fb4e0f466ffd\">sp_toplistbrowse</a> *tlb)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__types.html#ga31764fbd69618c10be173c6c03d4c1bc\">sp_artist</a> *&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__toplist.html#ga504cc45074d40c817dffbcc2906ef57f\">sp_toplistbrowse_artist</a> (<a class=\"el\" href=\"group__types.html#ga723de429cd073bcf5d13fb4e0f466ffd\">sp_toplistbrowse</a> *tlb, int index)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">int&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__toplist.html#ga69f5e70269c1eb08e1ddb1c77bb8c3e3\">sp_toplistbrowse_num_albums</a> (<a class=\"el\" href=\"group__types.html#ga723de429cd073bcf5d13fb4e0f466ffd\">sp_toplistbrowse</a> *tlb)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__types.html#ga6fd3e5de729c429fef3ff18ece6dcfad\">sp_album</a> *&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__toplist.html#gaa080ace445d269f56942ac3d7f1f157e\">sp_toplistbrowse_album</a> (<a class=\"el\" href=\"group__types.html#ga723de429cd073bcf5d13fb4e0f466ffd\">sp_toplistbrowse</a> *tlb, int index)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">int&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__toplist.html#gaeb0ddfd565474dc7e444aabebbc119b7\">sp_toplistbrowse_num_tracks</a> (<a class=\"el\" href=\"group__types.html#ga723de429cd073bcf5d13fb4e0f466ffd\">sp_toplistbrowse</a> *tlb)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__types.html#ga47bbd2262f0c8b5d7147af7d62198e48\">sp_track</a> *&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__toplist.html#gaf3d00b8bf089134a4f320a8d3d6ab683\">sp_toplistbrowse_track</a> (<a class=\"el\" href=\"group__types.html#ga723de429cd073bcf5d13fb4e0f466ffd\">sp_toplistbrowse</a> *tlb, int index)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">int&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__toplist.html#gab9cf87d6b6a8cbd8d36cd6e94a3270ee\">sp_toplistbrowse_backend_request_duration</a> (<a class=\"el\" href=\"group__types.html#ga723de429cd073bcf5d13fb4e0f466ffd\">sp_toplistbrowse</a> *tlb)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__types.html#gaec0f2e5098cebc05ce56adfc9b346510\">sp_inbox</a> *&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__inbox.html#gaee29e747ca10b36597d91689ae074aa2\">sp_inbox_post_tracks</a> (<a class=\"el\" href=\"group__types.html#ga70dd19c6f824cf6a159575aa4c128b53\">sp_session</a> *session, const char *user, <a class=\"el\" href=\"group__types.html#ga47bbd2262f0c8b5d7147af7d62198e48\">sp_track</a> *const *tracks, int num_tracks, const char *message, <a class=\"el\" href=\"group__inbox.html#ga5084d6ab753294730402a0c43b82e60c\">inboxpost_complete_cb</a> *callback, void *userdata)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__error.html#gafd27986ce4cd9eeaeca8adda83c9eb6b\">sp_error</a>&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__inbox.html#gaa452e9fe1fa7c9e2c780d28ce2ed63c5\">sp_inbox_error</a> (<a class=\"el\" href=\"group__types.html#gaec0f2e5098cebc05ce56adfc9b346510\">sp_inbox</a> *inbox)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__error.html#gafd27986ce4cd9eeaeca8adda83c9eb6b\">sp_error</a>&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__inbox.html#gadb6b607bc26b9d362de4da09ec1c864f\">sp_inbox_add_ref</a> (<a class=\"el\" href=\"group__types.html#gaec0f2e5098cebc05ce56adfc9b346510\">sp_inbox</a> *inbox)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__error.html#gafd27986ce4cd9eeaeca8adda83c9eb6b\">sp_error</a>&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__inbox.html#ga73659a65af92d30e4ac1cf3e06e74a0a\">sp_inbox_release</a> (<a class=\"el\" href=\"group__types.html#gaec0f2e5098cebc05ce56adfc9b346510\">sp_inbox</a> *inbox)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">const char *&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"api_8h.html#a181d0940997cb8b69869449cd826cf88\">sp_build_id</a> (void)</td></tr>\n</table>\n<hr/><a name=\"_details\"></a><h2>Detailed Description</h2>\n<p>Public API for libspotify</p>\n<dl class=\"note\"><dt><b>Note:</b></dt><dd>All input strings are expected to be in UTF-8 </dd>\n<dd>\nAll output strings are in UTF-8.</dd>\n<dd>\nAll usernames are valid XMPP nodeprep identifiers: <a href=\"http://tools.ietf.org/html/rfc3920#appendix-A\">http://tools.ietf.org/html/rfc3920#appendix-A</a> If you need to store user data, we strongly advise you to use the canonical form of the username. </dd></dl>\n<hr/><h2>Function Documentation</h2>\n<a class=\"anchor\" id=\"a181d0940997cb8b69869449cd826cf88\"></a><!-- doxytag: member=\"api.h::sp_build_id\" ref=\"a181d0940997cb8b69869449cd826cf88\" args=\"(void)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\">const char* sp_build_id </td>\n          <td>(</td>\n          <td class=\"paramtype\">void&nbsp;</td>\n          <td class=\"paramname\"></td>\n          <td>&nbsp;)&nbsp;</td>\n          <td></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Return the libspotify build ID</p>\n<p>This might be useful to have available for display somewhere in your user interface. </p>\n\n</div>\n</div>\n</div>\n<hr size=\"1\"><address style=\"text-align: right;\"><small>\nGenerated on Wed Jun 13 2012 14:22:40.<br>\nCopyright &copy; 2006&ndash;2012 Spotify Ltd</small></address>\n</body>\n</html>\n"
  },
  {
    "path": "libspotify/docs/html/browse_8c-example.html",
    "content": "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\n<html xmlns=\"http://www.w3.org/1999/xhtml\">\n<head>\n<meta http-equiv=\"Content-Type\" content=\"text/xhtml;charset=UTF-8\"/>\n<title>libspotify: browse.c</title>\n<link href=\"tabs.css\" rel=\"stylesheet\" type=\"text/css\"/>\n<link href=\"doxygen.css\" rel=\"stylesheet\" type=\"text/css\"/>\n</head>\n<body>\n<!-- Generated by Doxygen 1.7.1 -->\n<div class=\"navigation\" id=\"top\">\n  <div class=\"tabs\">\n    <ul class=\"tablist\">\n      <li><a href=\"index.html\"><span>Main&nbsp;Page</span></a></li>\n      <li><a href=\"modules.html\"><span>Modules</span></a></li>\n      <li><a href=\"annotated.html\"><span>Data&nbsp;Structures</span></a></li>\n      <li><a href=\"files.html\"><span>Files</span></a></li>\n      <li><a href=\"examples.html\"><span>Examples</span></a></li>\n    </ul>\n  </div>\n</div>\n<div class=\"header\">\n  <div class=\"headertitle\">\n<h1>browse.c</h1>  </div>\n</div>\n<div class=\"contents\">\n<p>The browse.c example shows how you can use the album, artist, and browse functions. The example also include some rudimentary playlist browsing. It is part of the spshell program</p>\n<div class=\"fragment\"><pre class=\"fragment\">\n<span class=\"preprocessor\">#include &quot;spshell.h&quot;</span>\n<span class=\"preprocessor\">#include &quot;cmd.h&quot;</span>\n\n<span class=\"keyword\">static</span> <a class=\"code\" href=\"group__types.html#ga47bbd2262f0c8b5d7147af7d62198e48\" title=\"A track handle.\">sp_track</a> *track_browse;\n<span class=\"keyword\">static</span> <a class=\"code\" href=\"group__types.html#ga1bcf54cbc117a20ab2c15e59eb3a8174\" title=\"A playlist handle.\">sp_playlist</a> *playlist_browse;\n<span class=\"keyword\">static</span> <a name=\"_a0\"></a><a class=\"code\" href=\"structsp__playlist__callbacks.html\">sp_playlist_callbacks</a> pl_callbacks;\n\n<span class=\"keywordtype\">void</span> print_track(<a class=\"code\" href=\"group__types.html#ga47bbd2262f0c8b5d7147af7d62198e48\" title=\"A track handle.\">sp_track</a> *track)\n{\n    <span class=\"keywordtype\">int</span> duration = <a name=\"a1\"></a><a class=\"code\" href=\"group__track.html#gac817937bd8d8355b6a1949b76d0b5560\">sp_track_duration</a>(track);\n    <span class=\"keywordtype\">char</span> url[256];\n    <a class=\"code\" href=\"group__types.html#gaf90a23d6b662c96d52ac19f7f4bc1e39\" title=\"A handle to the libspotify internal representation of a URI.\">sp_link</a> *l;\n    <span class=\"keywordtype\">int</span> i;\n\n<span class=\"preprocessor\">#if WIN32</span>\n<span class=\"preprocessor\"></span>    printf(<span class=\"stringliteral\">&quot; %s &quot;</span>, <a name=\"a2\"></a><a class=\"code\" href=\"group__track.html#gab17d380ac941e102af0f308ad885b3c3\">sp_track_is_starred</a>(g_session,track) ? <span class=\"stringliteral\">&quot;*&quot;</span> : <span class=\"stringliteral\">&quot; &quot;</span>);\n<span class=\"preprocessor\">#else</span>\n<span class=\"preprocessor\"></span>    printf(<span class=\"stringliteral\">&quot; %s &quot;</span>, <a class=\"code\" href=\"group__track.html#gab17d380ac941e102af0f308ad885b3c3\">sp_track_is_starred</a>(g_session,track) ? <span class=\"stringliteral\">&quot;★&quot;</span> : <span class=\"stringliteral\">&quot;☆&quot;</span>);\n<span class=\"preprocessor\">#endif</span>\n<span class=\"preprocessor\"></span>    printf(<span class=\"stringliteral\">&quot;Track %s [%d:%02d] has %d artist(s), %d%% popularity&quot;</span>,\n           <a name=\"a3\"></a><a class=\"code\" href=\"group__track.html#ga8eb423d3cc2cbfb743c7f23ffb8d0fad\">sp_track_name</a>(track),\n           duration / 60000,\n           (duration / 1000) % 60,\n           <a name=\"a4\"></a><a class=\"code\" href=\"group__track.html#ga0aa945fc43e35d36cc334a52735d83b2\">sp_track_num_artists</a>(track),\n           <a name=\"a5\"></a><a class=\"code\" href=\"group__track.html#ga4570f08f968edbff519b44d2241d2255\">sp_track_popularity</a>(track));\n    \n    <span class=\"keywordflow\">if</span>(<a name=\"a6\"></a><a class=\"code\" href=\"group__track.html#ga9d464ee4a5c8836b59888952b960223a\">sp_track_disc</a>(track)) \n        printf(<span class=\"stringliteral\">&quot;, %d on disc %d&quot;</span>,\n               <a name=\"a7\"></a><a class=\"code\" href=\"group__track.html#ga25c1df9d32fd58f243397740b29c3f61\">sp_track_index</a>(track),\n               <a class=\"code\" href=\"group__track.html#ga9d464ee4a5c8836b59888952b960223a\">sp_track_disc</a>(track));\n    printf(<span class=\"stringliteral\">&quot;\\n&quot;</span>);\n\n    <span class=\"keywordflow\">for</span> (i = 0; i &lt; <a class=\"code\" href=\"group__track.html#ga0aa945fc43e35d36cc334a52735d83b2\">sp_track_num_artists</a>(track); i++) {\n        <a class=\"code\" href=\"group__types.html#ga31764fbd69618c10be173c6c03d4c1bc\" title=\"An artist handle.\">sp_artist</a> *art = <a name=\"a8\"></a><a class=\"code\" href=\"group__track.html#ga67cd0c035627a1e4a54642213fdf1d75\">sp_track_artist</a>(track, i);\n        printf(<span class=\"stringliteral\">&quot;\\tArtist %d: %s\\n&quot;</span>, i + 1, <a name=\"a9\"></a><a class=\"code\" href=\"group__artist.html#gad2895555bb48514986823733a7afe5e2\">sp_artist_name</a>(art));\n    }\n    l = <a name=\"a10\"></a><a class=\"code\" href=\"group__link.html#ga82c29419ce70e2b504670e3d45167d5d\">sp_link_create_from_track</a>(track, 0);\n    <a name=\"a11\"></a><a class=\"code\" href=\"group__link.html#ga9f169be53f098adcf12f7a10b8bd3ef7\">sp_link_as_string</a>(l, url, <span class=\"keyword\">sizeof</span>(url));\n    printf(<span class=\"stringliteral\">&quot;\\t\\t%s\\n&quot;</span>, url);\n    <a name=\"a12\"></a><a class=\"code\" href=\"group__link.html#ga2b06ab16d1f6436cd8d36dbff2b5c022\">sp_link_release</a>(l);\n}\n\n<span class=\"keyword\">static</span> <span class=\"keywordtype\">void</span> print_albumbrowse(<a class=\"code\" href=\"group__types.html#ga9c4550473a7a07790778ba870c31b4d9\" title=\"A handle to an album browse result.\">sp_albumbrowse</a> *browse)\n{\n    <span class=\"keywordtype\">int</span> i;\n\n    printf(<span class=\"stringliteral\">&quot;Album browse of \\&quot;%s\\&quot; (%d)\\n&quot;</span>, \n           <a name=\"a13\"></a><a class=\"code\" href=\"group__album.html#ga0e828c991a8184d60026513f944e19ad\">sp_album_name</a>(<a name=\"a14\"></a><a class=\"code\" href=\"group__albumbrowse.html#gaf0dadfc4edb48a3558b606e30e8bedfa\">sp_albumbrowse_album</a>(browse)), \n           <a name=\"a15\"></a><a class=\"code\" href=\"group__album.html#ga2aadf934b0af43c3ef6ee98b6a8065fd\">sp_album_year</a>(<a class=\"code\" href=\"group__albumbrowse.html#gaf0dadfc4edb48a3558b606e30e8bedfa\">sp_albumbrowse_album</a>(browse)));\n\n    <span class=\"keywordflow\">for</span> (i = 0; i &lt; <a name=\"a16\"></a><a class=\"code\" href=\"group__albumbrowse.html#gab53fa74ee1958dad5186be09e70ddc4a\">sp_albumbrowse_num_copyrights</a>(browse); ++i)\n        printf(<span class=\"stringliteral\">&quot;  Copyright: %s\\n&quot;</span>, <a name=\"a17\"></a><a class=\"code\" href=\"group__albumbrowse.html#ga34b205daa2960e8d02a6e1accd80ab92\">sp_albumbrowse_copyright</a>(browse, i));\n\n    printf(<span class=\"stringliteral\">&quot;  Tracks: %d\\n&quot;</span>, <a name=\"a18\"></a><a class=\"code\" href=\"group__albumbrowse.html#ga3fb91de745ca07d3801a57288f2d9da7\">sp_albumbrowse_num_tracks</a>(browse));\n    printf(<span class=\"stringliteral\">&quot;  Review: %.60s...\\n&quot;</span>, <a name=\"a19\"></a><a class=\"code\" href=\"group__albumbrowse.html#ga868f3f3263f5033ae1fba60f403be712\">sp_albumbrowse_review</a>(browse));\n    puts(<span class=\"stringliteral\">&quot;&quot;</span>);\n\n    <span class=\"keywordflow\">for</span> (i = 0; i &lt; <a class=\"code\" href=\"group__albumbrowse.html#ga3fb91de745ca07d3801a57288f2d9da7\">sp_albumbrowse_num_tracks</a>(browse); ++i)\n        print_track(<a name=\"a20\"></a><a class=\"code\" href=\"group__albumbrowse.html#gad3c8df4b75158bba2c06aaefa74c5aa1\">sp_albumbrowse_track</a>(browse, i));\n\n    puts(<span class=\"stringliteral\">&quot;&quot;</span>);\n}\n\n<span class=\"keyword\">static</span> <span class=\"keywordtype\">void</span> print_artistbrowse(<a class=\"code\" href=\"group__types.html#gafd3d5aae485f1012ec91b7948e6f9f2b\" title=\"A handle to an artist browse result.\">sp_artistbrowse</a> *browse)\n{\n    <span class=\"keywordtype\">int</span> i;\n\n    printf(<span class=\"stringliteral\">&quot;Artist browse of \\&quot;%s\\&quot;\\n&quot;</span>, <a class=\"code\" href=\"group__artist.html#gad2895555bb48514986823733a7afe5e2\">sp_artist_name</a>(<a name=\"a21\"></a><a class=\"code\" href=\"group__artistbrowse.html#ga5f6a046b2bd261d7628582b986a9019f\">sp_artistbrowse_artist</a>(browse)));\n\n    <span class=\"keywordflow\">for</span> (i = 0; i &lt; <a name=\"a22\"></a><a class=\"code\" href=\"group__artistbrowse.html#ga2559638742416ac621af0e919e017d17\">sp_artistbrowse_num_similar_artists</a>(browse); ++i)\n        printf(<span class=\"stringliteral\">&quot;  Similar artist: %s\\n&quot;</span>, <a class=\"code\" href=\"group__artist.html#gad2895555bb48514986823733a7afe5e2\">sp_artist_name</a>(<a name=\"a23\"></a><a class=\"code\" href=\"group__artistbrowse.html#gac60ef4f9e006a920f1d72b6098743fbc\">sp_artistbrowse_similar_artist</a>(browse, i)));\n\n    printf(<span class=\"stringliteral\">&quot;  Portraits: %d\\n&quot;</span>, <a name=\"a24\"></a><a class=\"code\" href=\"group__artistbrowse.html#ga98dc47d36d2789999bfe62707c5041d7\">sp_artistbrowse_num_portraits</a>(browse));\n    printf(<span class=\"stringliteral\">&quot;  Tracks   : %d\\n&quot;</span>, <a name=\"a25\"></a><a class=\"code\" href=\"group__artistbrowse.html#ga8c862caa2234125ffcc4e93287b1e029\">sp_artistbrowse_num_tracks</a>(browse));\n    printf(<span class=\"stringliteral\">&quot;  Biography: %.60s...\\n&quot;</span>, <a name=\"a26\"></a><a class=\"code\" href=\"group__artistbrowse.html#ga8b93b9e5630662855f35694280ba4d2b\">sp_artistbrowse_biography</a>(browse));\n    puts(<span class=\"stringliteral\">&quot;&quot;</span>);\n\n    <span class=\"keywordflow\">for</span> (i = 0; i &lt; <a class=\"code\" href=\"group__artistbrowse.html#ga8c862caa2234125ffcc4e93287b1e029\">sp_artistbrowse_num_tracks</a>(browse); ++i)\n        print_track(<a name=\"a27\"></a><a class=\"code\" href=\"group__artistbrowse.html#ga45d28771a856f935dc40ab40e27dec4c\">sp_artistbrowse_track</a>(browse, i));\n\n    puts(<span class=\"stringliteral\">&quot;&quot;</span>);\n}\n\n\n\n<span class=\"keyword\">static</span> <span class=\"keywordtype\">void</span> SP_CALLCONV browse_album_callback(<a class=\"code\" href=\"group__types.html#ga9c4550473a7a07790778ba870c31b4d9\" title=\"A handle to an album browse result.\">sp_albumbrowse</a> *browse, <span class=\"keywordtype\">void</span> *userdata)\n{\n    <span class=\"keywordflow\">if</span> (<a name=\"a28\"></a><a class=\"code\" href=\"group__albumbrowse.html#ga153417eee319e7711b66503f88fba88b\">sp_albumbrowse_error</a>(browse) == <a name=\"a29\"></a><a class=\"code\" href=\"group__error.html#ggafd27986ce4cd9eeaeca8adda83c9eb6ba16cb277dc84328e4b2c0cf6d5a0c0b8d\" title=\"No errors encountered.\">SP_ERROR_OK</a>)\n        print_albumbrowse(browse);\n    <span class=\"keywordflow\">else</span>\n        fprintf(stderr, <span class=\"stringliteral\">&quot;Failed to browse album: %s\\n&quot;</span>,\n                <a name=\"a30\"></a><a class=\"code\" href=\"group__error.html#ga983dee341d3c2008830513b7cffe7bf3\">sp_error_message</a>(<a class=\"code\" href=\"group__albumbrowse.html#ga153417eee319e7711b66503f88fba88b\">sp_albumbrowse_error</a>(browse)));\n\n    <a name=\"a31\"></a><a class=\"code\" href=\"group__albumbrowse.html#gabdd5a4e3b2098166b67e35979f59613d\">sp_albumbrowse_release</a>(browse);\n    cmd_done();\n}\n\n\n<span class=\"keyword\">static</span> <span class=\"keywordtype\">void</span> SP_CALLCONV browse_artist_callback(<a class=\"code\" href=\"group__types.html#gafd3d5aae485f1012ec91b7948e6f9f2b\" title=\"A handle to an artist browse result.\">sp_artistbrowse</a> *browse, <span class=\"keywordtype\">void</span> *userdata)\n{\n    <span class=\"keywordflow\">if</span> (<a name=\"a32\"></a><a class=\"code\" href=\"group__artistbrowse.html#ga203e757088ff7a5098f16a1367da25d2\">sp_artistbrowse_error</a>(browse) == <a class=\"code\" href=\"group__error.html#ggafd27986ce4cd9eeaeca8adda83c9eb6ba16cb277dc84328e4b2c0cf6d5a0c0b8d\" title=\"No errors encountered.\">SP_ERROR_OK</a>)\n        print_artistbrowse(browse);\n    <span class=\"keywordflow\">else</span>\n        fprintf(stderr, <span class=\"stringliteral\">&quot;Failed to browse artist: %s\\n&quot;</span>,\n                <a class=\"code\" href=\"group__error.html#ga983dee341d3c2008830513b7cffe7bf3\">sp_error_message</a>(<a class=\"code\" href=\"group__artistbrowse.html#ga203e757088ff7a5098f16a1367da25d2\">sp_artistbrowse_error</a>(browse)));\n\n    <a name=\"a33\"></a><a class=\"code\" href=\"group__artistbrowse.html#ga14626a4f6a60b1caf61cb54c26783671\">sp_artistbrowse_release</a>(browse);\n    cmd_done();\n}\n\n\n\n<span class=\"keyword\">static</span> <span class=\"keywordtype\">void</span> track_browse_try(<span class=\"keywordtype\">void</span>)\n{\n    <span class=\"keywordflow\">switch</span> (<a name=\"a34\"></a><a class=\"code\" href=\"group__track.html#ga947c0f7755b0c4955ca0b0993db0f2b5\">sp_track_error</a>(track_browse)) {\n    <span class=\"keywordflow\">case</span> <a class=\"code\" href=\"group__error.html#ggafd27986ce4cd9eeaeca8adda83c9eb6ba16cb277dc84328e4b2c0cf6d5a0c0b8d\" title=\"No errors encountered.\">SP_ERROR_OK</a>:\n        print_track(track_browse);\n        <span class=\"keywordflow\">break</span>;\n\n    <span class=\"keywordflow\">case</span> <a name=\"a35\"></a><a class=\"code\" href=\"group__error.html#ggafd27986ce4cd9eeaeca8adda83c9eb6ba17f54c30d01baedc24547e62ed417cdd\" title=\"The resource is currently loading.\">SP_ERROR_IS_LOADING</a>:\n        <span class=\"keywordflow\">return</span>; <span class=\"comment\">// Still pending</span>\n\n    <span class=\"keywordflow\">default</span>:\n        fprintf(stderr, <span class=\"stringliteral\">&quot;Unable to resolve track: %s\\n&quot;</span>, <a class=\"code\" href=\"group__error.html#ga983dee341d3c2008830513b7cffe7bf3\">sp_error_message</a>(<a class=\"code\" href=\"group__track.html#ga947c0f7755b0c4955ca0b0993db0f2b5\">sp_track_error</a>(track_browse)));\n        <span class=\"keywordflow\">break</span>;\n    }\n    \n    metadata_updated_fn = NULL;\n    cmd_done();\n    <a name=\"a36\"></a><a class=\"code\" href=\"group__track.html#gaa11098d82e6c2ae42fc2ea1486e741de\">sp_track_release</a>(track_browse);\n}\n\n\n\n<span class=\"keyword\">static</span> <span class=\"keywordtype\">void</span> playlist_browse_try(<span class=\"keywordtype\">void</span>)\n{\n    <span class=\"keywordtype\">int</span> i, tracks;\n\n    metadata_updated_fn = playlist_browse_try;\n    <span class=\"keywordflow\">if</span>(!<a name=\"a37\"></a><a class=\"code\" href=\"group__playlist.html#gaee8ea6c07dfdca3397e27b278fa4870a\">sp_playlist_is_loaded</a>(playlist_browse)) {\n        printf(<span class=\"stringliteral\">&quot;\\tPlaylist not loaded\\n&quot;</span>);\n        <span class=\"keywordflow\">return</span>;\n    }\n\n    tracks = <a name=\"a38\"></a><a class=\"code\" href=\"group__playlist.html#ga684a3acc60f99b3b26488ed813ee5d23\">sp_playlist_num_tracks</a>(playlist_browse);\n    <span class=\"keywordflow\">for</span>(i = 0; i &lt; tracks; i++) {\n        <a class=\"code\" href=\"group__types.html#ga47bbd2262f0c8b5d7147af7d62198e48\" title=\"A track handle.\">sp_track</a> *t = <a name=\"a39\"></a><a class=\"code\" href=\"group__playlist.html#ga7a03854fe6072476306780d23c6cac16\">sp_playlist_track</a>(playlist_browse, i);\n        <span class=\"keywordflow\">if</span> (!<a name=\"a40\"></a><a class=\"code\" href=\"group__track.html#ga8b69cf193679c7e00031ae43e61c6a54\">sp_track_is_loaded</a>(t))\n            <span class=\"keywordflow\">return</span>;\n    }\n\n    printf(<span class=\"stringliteral\">&quot;\\tPlaylist and metadata loaded\\n&quot;</span>);\n\n    <span class=\"keywordflow\">for</span>(i = 0; i &lt; tracks; i++) {\n        <a class=\"code\" href=\"group__types.html#ga47bbd2262f0c8b5d7147af7d62198e48\" title=\"A track handle.\">sp_track</a> *t = <a class=\"code\" href=\"group__playlist.html#ga7a03854fe6072476306780d23c6cac16\">sp_playlist_track</a>(playlist_browse, i);\n        \n        printf(<span class=\"stringliteral\">&quot; %5d: &quot;</span>, i + 1);\n        print_track(t);\n    }\n    <a name=\"a41\"></a><a class=\"code\" href=\"group__playlist.html#ga7fcbf909a0fa8bf25f0b1d1e7dd0e160\">sp_playlist_remove_callbacks</a>(playlist_browse, &amp;pl_callbacks, NULL);\n\n    <a name=\"a42\"></a><a class=\"code\" href=\"group__playlist.html#gacb9250eb530869b039541a8b62dfab6c\">sp_playlist_release</a>(playlist_browse);\n    playlist_browse = NULL;\n    metadata_updated_fn = NULL;\n    cmd_done();\n}\n\n<span class=\"keyword\">static</span> <span class=\"keywordtype\">void</span> SP_CALLCONV pl_tracks_added(<a class=\"code\" href=\"group__types.html#ga1bcf54cbc117a20ab2c15e59eb3a8174\" title=\"A playlist handle.\">sp_playlist</a> *pl, <a class=\"code\" href=\"group__types.html#ga47bbd2262f0c8b5d7147af7d62198e48\" title=\"A track handle.\">sp_track</a> * <span class=\"keyword\">const</span> * tracks,\n                <span class=\"keywordtype\">int</span> num_tracks, <span class=\"keywordtype\">int</span> position, <span class=\"keywordtype\">void</span> *userdata)\n{\n    printf(<span class=\"stringliteral\">&quot;\\t%d tracks added\\n&quot;</span>, num_tracks);\n}\n\n<span class=\"keyword\">static</span> <span class=\"keywordtype\">void</span> SP_CALLCONV pl_tracks_removed(<a class=\"code\" href=\"group__types.html#ga1bcf54cbc117a20ab2c15e59eb3a8174\" title=\"A playlist handle.\">sp_playlist</a> *pl, <span class=\"keyword\">const</span> <span class=\"keywordtype\">int</span> *tracks,\n                  <span class=\"keywordtype\">int</span> num_tracks, <span class=\"keywordtype\">void</span> *userdata)\n{\n    printf(<span class=\"stringliteral\">&quot;\\t%d tracks removed\\n&quot;</span>, num_tracks);\n}\n\n<span class=\"keyword\">static</span> <span class=\"keywordtype\">void</span> SP_CALLCONV pl_tracks_moved(<a class=\"code\" href=\"group__types.html#ga1bcf54cbc117a20ab2c15e59eb3a8174\" title=\"A playlist handle.\">sp_playlist</a> *pl, <span class=\"keyword\">const</span> <span class=\"keywordtype\">int</span> *tracks,\n                <span class=\"keywordtype\">int</span> num_tracks, <span class=\"keywordtype\">int</span> new_position, <span class=\"keywordtype\">void</span> *userdata)\n{\n    printf(<span class=\"stringliteral\">&quot;\\t%d tracks moved\\n&quot;</span>, num_tracks);\n}\n\n<span class=\"keyword\">static</span> <span class=\"keywordtype\">void</span> SP_CALLCONV pl_renamed(<a class=\"code\" href=\"group__types.html#ga1bcf54cbc117a20ab2c15e59eb3a8174\" title=\"A playlist handle.\">sp_playlist</a> *pl, <span class=\"keywordtype\">void</span> *userdata)\n{\n    printf(<span class=\"stringliteral\">&quot;\\tList name: %s\\n&quot;</span>,  <a name=\"a43\"></a><a class=\"code\" href=\"group__playlist.html#ga61b7e33cc1aedb4e31a2af75ae0ac8cc\">sp_playlist_name</a>(pl));\n}\n\n<span class=\"keyword\">static</span> <span class=\"keywordtype\">void</span> SP_CALLCONV pl_state_change(<a class=\"code\" href=\"group__types.html#ga1bcf54cbc117a20ab2c15e59eb3a8174\" title=\"A playlist handle.\">sp_playlist</a> *pl, <span class=\"keywordtype\">void</span> *userdata)\n{\n    playlist_browse_try();\n}\n\n<span class=\"keyword\">static</span> <a class=\"code\" href=\"structsp__playlist__callbacks.html\">sp_playlist_callbacks</a> pl_callbacks = {\n    pl_tracks_added,\n    pl_tracks_removed,\n    pl_tracks_moved,\n    pl_renamed,\n    pl_state_change,\n};\n\n\n<span class=\"keywordtype\">void</span> browse_playlist(<a class=\"code\" href=\"group__types.html#ga1bcf54cbc117a20ab2c15e59eb3a8174\" title=\"A playlist handle.\">sp_playlist</a> *pl)\n{\n    playlist_browse = pl;\n    <a name=\"a44\"></a><a class=\"code\" href=\"group__playlist.html#gab15fca12d387c69b4998a4d2b48e5b32\">sp_playlist_add_callbacks</a>(playlist_browse, &amp;pl_callbacks, NULL);\n    playlist_browse_try();\n}\n\n<span class=\"keyword\">static</span> <span class=\"keywordtype\">void</span> browse_usage(<span class=\"keywordtype\">void</span>)\n{\n    fprintf(stderr, <span class=\"stringliteral\">&quot;Usage: browse &lt;spotify-uri&gt;\\n&quot;</span>);\n}\n\n\n<span class=\"keywordtype\">int</span> cmd_browse(<span class=\"keywordtype\">int</span> argc, <span class=\"keywordtype\">char</span> **argv)\n{\n    <a class=\"code\" href=\"group__types.html#gaf90a23d6b662c96d52ac19f7f4bc1e39\" title=\"A handle to the libspotify internal representation of a URI.\">sp_link</a> *link;\n\n    <span class=\"keywordflow\">if</span> (argc != 2) {\n        browse_usage();\n        <span class=\"keywordflow\">return</span> -1;\n    }\n\n    \n    link = <a name=\"a45\"></a><a class=\"code\" href=\"group__link.html#gaea9c39f35f7986fc9fed4584fa211127\">sp_link_create_from_string</a>(argv[1]);\n    \n    <span class=\"keywordflow\">if</span> (!link) {\n        fprintf(stderr, <span class=\"stringliteral\">&quot;Not a spotify link\\n&quot;</span>);\n        <span class=\"keywordflow\">return</span> -1;\n    }\n\n    <span class=\"keywordflow\">switch</span>(<a name=\"a46\"></a><a class=\"code\" href=\"group__link.html#ga6140f924c696d53469bb8930cd53e1e6\">sp_link_type</a>(link)) {\n    <span class=\"keywordflow\">default</span>:\n        fprintf(stderr, <span class=\"stringliteral\">&quot;Can not handle link&quot;</span>);\n        <a class=\"code\" href=\"group__link.html#ga2b06ab16d1f6436cd8d36dbff2b5c022\">sp_link_release</a>(link);\n        <span class=\"keywordflow\">return</span> -1;\n\n    <span class=\"keywordflow\">case</span> <a name=\"a47\"></a><a class=\"code\" href=\"group__link.html#ggabe9611f04086cdbed6e4e6e1fd913b98a7716eb95eed852d08300e6e64febc7f3\" title=\"Link type is album.\">SP_LINKTYPE_ALBUM</a>:\n        <a name=\"a48\"></a><a class=\"code\" href=\"group__albumbrowse.html#gaf1bc3042e748efea5ca7ac159e5cbfbe\">sp_albumbrowse_create</a>(g_session, <a name=\"a49\"></a><a class=\"code\" href=\"group__link.html#gaafa98628d0abadcca27dd3b227c7337b\">sp_link_as_album</a>(link), browse_album_callback, NULL);\n        <span class=\"keywordflow\">break</span>;\n\n    <span class=\"keywordflow\">case</span> <a name=\"a50\"></a><a class=\"code\" href=\"group__link.html#ggabe9611f04086cdbed6e4e6e1fd913b98a4402b3b001aebb39fd55296f83c60b7e\" title=\"Link type is artist.\">SP_LINKTYPE_ARTIST</a>:\n        <a name=\"a51\"></a><a class=\"code\" href=\"group__artistbrowse.html#ga8dd8364b2fcd29c846209660bd9a69b2\">sp_artistbrowse_create</a>(g_session, <a name=\"a52\"></a><a class=\"code\" href=\"group__link.html#gab32979d26dcf68936202fa7aed7b6e49\">sp_link_as_artist</a>(link), <a name=\"a53\"></a><a class=\"code\" href=\"group__session.html#ggac86504cc9e8cadbc30c8aa8dbf355034a2914168528aded818177c013a0dd7e87\">SP_ARTISTBROWSE_FULL</a>, browse_artist_callback, NULL);\n        <span class=\"keywordflow\">break</span>;\n\n    <span class=\"keywordflow\">case</span> <a name=\"a54\"></a><a class=\"code\" href=\"group__link.html#ggabe9611f04086cdbed6e4e6e1fd913b98a0698cd0123190c7af55daf79bb642805\" title=\"Link type is a local file.\">SP_LINKTYPE_LOCALTRACK</a>:\n    <span class=\"keywordflow\">case</span> <a name=\"a55\"></a><a class=\"code\" href=\"group__link.html#ggabe9611f04086cdbed6e4e6e1fd913b98a5911dbb7258ed160b2f9c114cef152f1\" title=\"Link type is track.\">SP_LINKTYPE_TRACK</a>:\n        track_browse = <a name=\"a56\"></a><a class=\"code\" href=\"group__link.html#ga2560687997d7ce0fbf4f05251d87d32a\">sp_link_as_track</a>(link);\n        metadata_updated_fn = track_browse_try;\n        <a name=\"a57\"></a><a class=\"code\" href=\"group__track.html#ga7d86041a2bf75590f55978521c08e38c\">sp_track_add_ref</a>(track_browse);\n        track_browse_try();\n        <span class=\"keywordflow\">break</span>;\n\n    <span class=\"keywordflow\">case</span> <a name=\"a58\"></a><a class=\"code\" href=\"group__link.html#ggabe9611f04086cdbed6e4e6e1fd913b98a2640ed065a64b6a9f67e71bbeb2af2dd\" title=\"Link type is playlist.\">SP_LINKTYPE_PLAYLIST</a>:\n        browse_playlist(<a name=\"a59\"></a><a class=\"code\" href=\"group__playlist.html#ga342a6a0cfe10531ef7cb3c6629c1e8e7\">sp_playlist_create</a>(g_session, link));\n        <span class=\"keywordflow\">break</span>;\n    }\n\n    <a class=\"code\" href=\"group__link.html#ga2b06ab16d1f6436cd8d36dbff2b5c022\">sp_link_release</a>(link);\n    <span class=\"keywordflow\">return</span> 0;\n}\n</pre></div> </div>\n</div>\n<hr size=\"1\"><address style=\"text-align: right;\"><small>\nGenerated on Wed Jun 13 2012 14:22:40.<br>\nCopyright &copy; 2006&ndash;2012 Spotify Ltd</small></address>\n</body>\n</html>\n"
  },
  {
    "path": "libspotify/docs/html/classes.html",
    "content": "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\n<html xmlns=\"http://www.w3.org/1999/xhtml\">\n<head>\n<meta http-equiv=\"Content-Type\" content=\"text/xhtml;charset=UTF-8\"/>\n<title>libspotify: Alphabetical List</title>\n<link href=\"tabs.css\" rel=\"stylesheet\" type=\"text/css\"/>\n<link href=\"doxygen.css\" rel=\"stylesheet\" type=\"text/css\"/>\n</head>\n<body>\n<!-- Generated by Doxygen 1.7.1 -->\n<div class=\"navigation\" id=\"top\">\n  <div class=\"tabs\">\n    <ul class=\"tablist\">\n      <li><a href=\"index.html\"><span>Main&nbsp;Page</span></a></li>\n      <li><a href=\"modules.html\"><span>Modules</span></a></li>\n      <li class=\"current\"><a href=\"annotated.html\"><span>Data&nbsp;Structures</span></a></li>\n      <li><a href=\"files.html\"><span>Files</span></a></li>\n      <li><a href=\"examples.html\"><span>Examples</span></a></li>\n    </ul>\n  </div>\n  <div class=\"tabs2\">\n    <ul class=\"tablist\">\n      <li><a href=\"annotated.html\"><span>Data&nbsp;Structures</span></a></li>\n      <li><a href=\"functions.html\"><span>Data&nbsp;Fields</span></a></li>\n    </ul>\n  </div>\n</div>\n<div class=\"header\">\n  <div class=\"headertitle\">\n<h1>Data Structure Index</h1>  </div>\n</div>\n<div class=\"contents\">\n<div class=\"qindex\"><a class=\"qindex\" href=\"#letter_S\">S</a></div>\n<table align=\"center\" width=\"95%\" border=\"0\" cellspacing=\"0\" cellpadding=\"0\">\n<tr><td><a name=\"letter_S\"></a><table border=\"0\" cellspacing=\"0\" cellpadding=\"0\"><tr><td><div class=\"ah\">&nbsp;&nbsp;S&nbsp;&nbsp;</div></td></tr></table>\n</td><td><a class=\"el\" href=\"structsp__audioformat.html\">sp_audioformat</a>&nbsp;&nbsp;&nbsp;</td><td><a class=\"el\" href=\"structsp__playlist__callbacks.html\">sp_playlist_callbacks</a>&nbsp;&nbsp;&nbsp;</td><td><a class=\"el\" href=\"structsp__session__callbacks.html\">sp_session_callbacks</a>&nbsp;&nbsp;&nbsp;</td><td><a class=\"el\" href=\"structsp__subscribers.html\">sp_subscribers</a>&nbsp;&nbsp;&nbsp;</td></tr><tr><td><a class=\"el\" href=\"structsp__audio__buffer__stats.html\">sp_audio_buffer_stats</a>&nbsp;&nbsp;&nbsp;</td><td><a class=\"el\" href=\"structsp__offline__sync__status.html\">sp_offline_sync_status</a>&nbsp;&nbsp;&nbsp;</td><td><a class=\"el\" href=\"structsp__playlistcontainer__callbacks.html\">sp_playlistcontainer_callbacks</a>&nbsp;&nbsp;&nbsp;</td><td><a class=\"el\" href=\"structsp__session__config.html\">sp_session_config</a>&nbsp;&nbsp;&nbsp;</td></tr></table><div class=\"qindex\"><a class=\"qindex\" href=\"#letter_S\">S</a></div>\n</div>\n<hr size=\"1\"><address style=\"text-align: right;\"><small>\nGenerated on Wed Jun 13 2012 14:22:40.<br>\nCopyright &copy; 2006&ndash;2012 Spotify Ltd</small></address>\n</body>\n</html>\n"
  },
  {
    "path": "libspotify/docs/html/doxygen.css",
    "content": "/* Copyright (c) 2009 Spotify Ltd */\nbody { margin:0; background:#fff; color:#444; padding:0; }\nbody,h1,h2,h3,h4,h5,p,td,li { font-family:'Helvetica neue',sans-serif; color:#000; }\nbody,td,p,li,div { line-height:1.5em; font-size:14px; color:#444; }\n\n/* @group Heading Levels */\nh1,h2,h3,h4,h5 { color:#222; }\nh1 > a, h2 > a, h3 > a, h4 > a { color:#222; }\nh1 { font-size: 180%; }\nh2 { font-size: 150%; margin-top:2em; }\ntd h2 { margin-top:0.5em; font-weight:normal; }\nh3 { font-size: 120%; }\n\n/* @end */\n\ncaption { font-weight: bold; }\n\ndiv.qindex, div.navtab {\n  background-color: #e8eef2;\n  border: 1px solid #84b0c7;\n  text-align: center;\n  margin: 2px;\n  padding: 2px;\n}\ndiv.qindex, div.navpath { width:100%; line-height:140%; }\ndiv.navtab { margin-right: 15px; }\ndiv.contents { margin:0 3em; }\n\n/* @group Link Styling */\n\ndiv.contents a { text-decoration:none; }\ndiv.contents a:link { color:#266a99; }\ndiv.contents a:hover { text-decoration:underline; }\ndiv.contents a:visited { color:#606a99; }\ndiv.contents a:link:hover { color:#006be4; background:#e2f4ff; }\ndiv.contents a:visited:hover { color:#af00cf; background:#f4e6ff; }\n\na.qindex { font-weight: bold; }\na.qindexHL {\n  font-weight: bold;\n  background-color: #6666cc;\n  color: #ffffff;\n  border: 1px double #9295C2;\n}\n.contents a.qindexHL:visited { color: #ffffff; }\na.el { font-weight: bold; }\na.elRef {}\na.code {}\na.codeRef {}\n\n/* @end */\n\ndl.el { margin-left: -1cm; }\n.fragment { font-family: monospace, fixed; }\npre.fragment {\n  border: 3px solid #fff;\n  background-color: #f0f3d9;\n  color:#38330b;\n  padding: 1em;\n  margin: 1em 0;\n}\ndiv.ah {\n  background-color: black;\n  font-weight: bold;\n  color: #ffffff;\n  margin-bottom: 3px;\n  margin-top: 3px\n}\n\ndiv.groupHeader {\n  margin-left: 16px;\n  margin-top: 12px;\n  margin-bottom: 6px;\n  font-weight: bold;\n}\ndiv.groupText { margin-left: 16px; font-style: italic; }\n\ndiv.navigation { margin-bottom:2em; }\n\ntd.indexkey {\n  background-color: #e8eef2;\n  font-weight: bold;\n  border: 1px solid #CCCCCC;\n  margin: 2px 0px 2px 0;\n  padding: 2px 10px;\n}\ntd.indexvalue {\n  background-color: #e8eef2;\n  border: 1px solid #CCCCCC;\n  padding: 2px 10px;\n  margin: 2px 0px;\n}\n\ntr.memlist { background-color: #f0f0f0; }\np.formulaDsp { text-align: center; }\nimg.formulaDsp {}\nimg.formulaInl { vertical-align: middle; }\n\n/* @group Code Colorization */\nspan.keyword { color: #2550b0; }\nspan.keywordtype { color: #604020; }\nspan.keywordflow { color: #9d5303; }\nspan.comment { color: #8f9277; font-style:italic; }\nspan.preprocessor { color: #806020; }\nspan.stringliteral { color: #1d783b; }\nspan.charliteral { color: #008080; }\nspan.vhdldigit { color: #ff00ff; }\nspan.vhdlchar { color: #000000; }\nspan.vhdlkeyword { color: #700070; }\nspan.vhdllogic { color: #ff0000; }\n\n/* @end */\n.search { color:#003399; font-weight:bold; }\nform.search { margin-bottom:0px; margin-top:0px; }\ninput.search {\n  font-size:75%;\n  color:#000080;\n  font-weight:normal;\n  background-color:#e8eef2;\n}\ntd.tiny { font-size: 75%; }\n.dirtab {\n  padding: 4px;\n  border-collapse: collapse;\n  border: 1px solid #84b0c7;\n}\nth.dirtab { background: #e8eef2; font-weight: bold; }\nhr { height:0; border:none; border-top:1px solid #ccc; }\n\n/* @group Member Descriptions */\n.mdescLeft, .mdescRight,\n.memItemLeft, .memItemRight,\n.memTemplItemLeft, .memTemplItemRight, .memTemplParams {\n  background-color: #eee;\n  border: none;\n  margin: 4px;\n  padding: 0.2em;\n  font-family:monospace;\n}\n.mdescLeft, .memItemLeft, .memTemplItemLeft { padding-left:1em; }\n.mdescRight, .memItemRight, .memTemplItemRight { padding-right:1em; }\n.mdescLeft, .mdescRight { padding: 0px 8px 4px 8px; color: #555; }\n.memItemLeft, .memItemRight, .memTemplParams { border-top: 1px solid #ccc; }\n.memTemplParams { color: #606060; }\n\n/* @end */\n\n/* @group Member Details */\n\n/* Styles for detailed member documentation */\n.memtemplate {\n  font-size: 80%;\n  color: #606060;\n  font-weight: normal;\n  margin-left: 3px;\n}\n.memnav {\n  background-color: #e8eef2;\n  border: 1px solid #84b0c7;\n  text-align: center;\n  margin: 2px;\n  margin-right: 15px;\n  padding: 2px;\n}\n.memitem { padding: 0; }\n.memname { white-space:nowrap; font-weight:bold; }\n.memproto, .memdoc {}\n.memproto {\n  padding: 0.3em 0.8em;\n  background-color: #cae2c9;\n  font-weight: bold;\n  -webkit-border-top-left-radius: 8px;\n  -webkit-border-top-right-radius: 8px;\n  -moz-border-radius-topleft: 8px;\n  -moz-border-radius-topright: 8px;\n}\n.memproto td { font-family:monospace; }\n.memproto td, .memdoc td { color:#103a0f; }\n.memdoc {\n  padding: 0.3em 0.8em;\n  background-color: #eaf5e9;\n  border-top-width: 0;\n  -webkit-border-bottom-left-radius: 8px;\n  -webkit-border-bottom-right-radius: 8px;\n  -moz-border-radius-bottomleft: 8px;\n  -moz-border-radius-bottomright: 8px;\n}\n\n.paramkey { text-align:right; }\n.paramtype { white-space:nowrap; }\n.paramname { color:#602020; white-space:nowrap; }\n.paramname em { font-style: normal; }\n\n/* @end */\n\n/* @group Directory (tree) */\n\n/* for the tree view */\n.ftvtree { font-family:sans-serif; margin:0.5em; }\n\n/* these are for tree view when used as main index */\n.directory { font-size: 9pt; font-weight: bold; }\n.directory h3 { margin: 0px; margin-top: 1em;  font-size: 11pt; }\n\n/*\nThe following two styles can be used to replace the root node title\nwith an image of your choice.  Simply uncomment the next two styles,\nspecify the name of your image and be sure to set 'height' to the\nproper pixel height of your image.\n*/\n\n/*\n.directory h3.swap {\n  height: 61px;\n  background-repeat: no-repeat;\n  background-image: url(\"yourimage.gif\");\n}\n.directory h3.swap span { display: none; }\n*/\n\n.directory > h3 { margin-top: 0; }\n.directory p { margin: 0px; white-space: nowrap; }\n.directory div { display: none; margin: 0px; }\n.directory img { vertical-align:-30%; }\n\n/* these are for tree view when not used as main index */\n.directory-alt { font-size: 100%; font-weight: bold; }\n.directory-alt h3 { margin: 0px; margin-top: 1em; font-size: 11pt; }\n.directory-alt > h3 { margin-top: 0; }\n.directory-alt p { margin: 0px; white-space: nowrap; }\n.directory-alt div { display: none; margin: 0px; }\n.directory-alt img { vertical-align: -30%; }\n\n/* @end */\n\n/* Footer */\nbody > hr { margin-top:4em; }\nbody > address {\n  padding:0 3em;\n  font-style: normal;\n  color: #999;\n  margin-bottom:.5em;\n  text-align:left !important;\n}\nbody > address br { display:none; }\n\n/* print */\n@media print {\n  div.contents {\n    padding-left:10%;\n    padding-right:6%;\n  }\n}\n"
  },
  {
    "path": "libspotify/docs/html/examples.html",
    "content": "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\n<html xmlns=\"http://www.w3.org/1999/xhtml\">\n<head>\n<meta http-equiv=\"Content-Type\" content=\"text/xhtml;charset=UTF-8\"/>\n<title>libspotify: Examples</title>\n<link href=\"tabs.css\" rel=\"stylesheet\" type=\"text/css\"/>\n<link href=\"doxygen.css\" rel=\"stylesheet\" type=\"text/css\"/>\n</head>\n<body>\n<!-- Generated by Doxygen 1.7.1 -->\n<div class=\"navigation\" id=\"top\">\n  <div class=\"tabs\">\n    <ul class=\"tablist\">\n      <li><a href=\"index.html\"><span>Main&nbsp;Page</span></a></li>\n      <li><a href=\"modules.html\"><span>Modules</span></a></li>\n      <li><a href=\"annotated.html\"><span>Data&nbsp;Structures</span></a></li>\n      <li><a href=\"files.html\"><span>Files</span></a></li>\n      <li class=\"current\"><a href=\"examples.html\"><span>Examples</span></a></li>\n    </ul>\n  </div>\n</div>\n<div class=\"header\">\n  <div class=\"headertitle\">\n<h1>Examples</h1>  </div>\n</div>\n<div class=\"contents\">\nHere is a list of all examples:<ul>\n<li><a class=\"el\" href=\"browse_8c-example.html\">browse.c</a></li>\n\n<li><a class=\"el\" href=\"jukebox_8c-example.html\">jukebox.c</a></li>\n\n<li><a class=\"el\" href=\"search_8c-example.html\">search.c</a></li>\n\n<li><a class=\"el\" href=\"toplist_8c-example.html\">toplist.c</a></li>\n\n</ul>\n</div>\n<hr size=\"1\"><address style=\"text-align: right;\"><small>\nGenerated on Wed Jun 13 2012 14:22:40.<br>\nCopyright &copy; 2006&ndash;2012 Spotify Ltd</small></address>\n</body>\n</html>\n"
  },
  {
    "path": "libspotify/docs/html/files.html",
    "content": "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\n<html xmlns=\"http://www.w3.org/1999/xhtml\">\n<head>\n<meta http-equiv=\"Content-Type\" content=\"text/xhtml;charset=UTF-8\"/>\n<title>libspotify: File Index</title>\n<link href=\"tabs.css\" rel=\"stylesheet\" type=\"text/css\"/>\n<link href=\"doxygen.css\" rel=\"stylesheet\" type=\"text/css\"/>\n</head>\n<body>\n<!-- Generated by Doxygen 1.7.1 -->\n<div class=\"navigation\" id=\"top\">\n  <div class=\"tabs\">\n    <ul class=\"tablist\">\n      <li><a href=\"index.html\"><span>Main&nbsp;Page</span></a></li>\n      <li><a href=\"modules.html\"><span>Modules</span></a></li>\n      <li><a href=\"annotated.html\"><span>Data&nbsp;Structures</span></a></li>\n      <li class=\"current\"><a href=\"files.html\"><span>Files</span></a></li>\n      <li><a href=\"examples.html\"><span>Examples</span></a></li>\n    </ul>\n  </div>\n  <div class=\"tabs2\">\n    <ul class=\"tablist\">\n      <li class=\"current\"><a href=\"files.html\"><span>File&nbsp;List</span></a></li>\n      <li><a href=\"globals.html\"><span>Globals</span></a></li>\n    </ul>\n  </div>\n</div>\n<div class=\"header\">\n  <div class=\"headertitle\">\n<h1>File List</h1>  </div>\n</div>\n<div class=\"contents\">\nHere is a list of all documented files with brief descriptions:<table>\n  <tr><td class=\"indexkey\"><a class=\"el\" href=\"api_8h.html\">api.h</a></td><td class=\"indexvalue\"></td></tr>\n</table>\n</div>\n<hr size=\"1\"><address style=\"text-align: right;\"><small>\nGenerated on Wed Jun 13 2012 14:22:40.<br>\nCopyright &copy; 2006&ndash;2012 Spotify Ltd</small></address>\n</body>\n</html>\n"
  },
  {
    "path": "libspotify/docs/html/functions.html",
    "content": "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\n<html xmlns=\"http://www.w3.org/1999/xhtml\">\n<head>\n<meta http-equiv=\"Content-Type\" content=\"text/xhtml;charset=UTF-8\"/>\n<title>libspotify: Data Fields</title>\n<link href=\"tabs.css\" rel=\"stylesheet\" type=\"text/css\"/>\n<link href=\"doxygen.css\" rel=\"stylesheet\" type=\"text/css\"/>\n</head>\n<body>\n<!-- Generated by Doxygen 1.7.1 -->\n<div class=\"navigation\" id=\"top\">\n  <div class=\"tabs\">\n    <ul class=\"tablist\">\n      <li><a href=\"index.html\"><span>Main&nbsp;Page</span></a></li>\n      <li><a href=\"modules.html\"><span>Modules</span></a></li>\n      <li class=\"current\"><a href=\"annotated.html\"><span>Data&nbsp;Structures</span></a></li>\n      <li><a href=\"files.html\"><span>Files</span></a></li>\n      <li><a href=\"examples.html\"><span>Examples</span></a></li>\n    </ul>\n  </div>\n  <div class=\"tabs2\">\n    <ul class=\"tablist\">\n      <li><a href=\"annotated.html\"><span>Data&nbsp;Structures</span></a></li>\n      <li class=\"current\"><a href=\"functions.html\"><span>Data&nbsp;Fields</span></a></li>\n    </ul>\n  </div>\n  <div class=\"tabs2\">\n    <ul class=\"tablist\">\n      <li class=\"current\"><a href=\"functions.html\"><span>All</span></a></li>\n      <li><a href=\"functions_vars.html\"><span>Variables</span></a></li>\n    </ul>\n  </div>\n  <div class=\"tabs3\">\n    <ul class=\"tablist\">\n      <li><a href=\"#index_a\"><span>a</span></a></li>\n      <li><a href=\"#index_c\"><span>c</span></a></li>\n      <li><a href=\"#index_d\"><span>d</span></a></li>\n      <li><a href=\"#index_e\"><span>e</span></a></li>\n      <li><a href=\"#index_g\"><span>g</span></a></li>\n      <li><a href=\"#index_i\"><span>i</span></a></li>\n      <li><a href=\"#index_l\"><span>l</span></a></li>\n      <li><a href=\"#index_m\"><span>m</span></a></li>\n      <li><a href=\"#index_n\"><span>n</span></a></li>\n      <li><a href=\"#index_o\"><span>o</span></a></li>\n      <li><a href=\"#index_p\"><span>p</span></a></li>\n      <li><a href=\"#index_q\"><span>q</span></a></li>\n      <li><a href=\"#index_s\"><span>s</span></a></li>\n      <li><a href=\"#index_t\"><span>t</span></a></li>\n      <li><a href=\"#index_u\"><span>u</span></a></li>\n      <li><a href=\"#index_w\"><span>w</span></a></li>\n    </ul>\n  </div>\n</div>\n<div class=\"contents\">\nHere is a list of all documented struct and union fields with links to the struct/union documentation for each field:\n\n<h3><a class=\"anchor\" id=\"index_a\"></a>- a -</h3><ul>\n<li>api_version\n: <a class=\"el\" href=\"structsp__session__config.html#a1ed9d4ff26e6f666ba96dce41d5f1bac\">sp_session_config</a>\n</li>\n<li>application_key\n: <a class=\"el\" href=\"structsp__session__config.html#ab5a5296a8e34bb454e7575940a19b9ae\">sp_session_config</a>\n</li>\n<li>application_key_size\n: <a class=\"el\" href=\"structsp__session__config.html#ab10b332fe29b941162fd1d9ea1003b82\">sp_session_config</a>\n</li>\n</ul>\n\n\n<h3><a class=\"anchor\" id=\"index_c\"></a>- c -</h3><ul>\n<li>ca_certs_filename\n: <a class=\"el\" href=\"structsp__session__config.html#a4a94ad4270e5401e68587952661bd3ca\">sp_session_config</a>\n</li>\n<li>cache_location\n: <a class=\"el\" href=\"structsp__session__config.html#ad1cb5e3670451d8cee3d8c9766b523fc\">sp_session_config</a>\n</li>\n<li>callbacks\n: <a class=\"el\" href=\"structsp__session__config.html#af0b456e6b9228ed812cd8ad28acbb127\">sp_session_config</a>\n</li>\n<li>channels\n: <a class=\"el\" href=\"structsp__audioformat.html#ab6b47d8d0ebfaab73229d707dc8bf0b8\">sp_audioformat</a>\n</li>\n<li>compress_playlists\n: <a class=\"el\" href=\"structsp__session__config.html#a8413a38bf3db9047b45525ac5dd4bc7b\">sp_session_config</a>\n</li>\n<li>connection_error\n: <a class=\"el\" href=\"structsp__session__callbacks.html#a45bf5d3fac7953099a191ea39fcfc018\">sp_session_callbacks</a>\n</li>\n<li>connectionstate_updated\n: <a class=\"el\" href=\"structsp__session__callbacks.html#a379c96577e927d6c65ac61fe13c1e412\">sp_session_callbacks</a>\n</li>\n<li>container_loaded\n: <a class=\"el\" href=\"structsp__playlistcontainer__callbacks.html#a8a0c301dd9cf90cccb4657a7d65c61b1\">sp_playlistcontainer_callbacks</a>\n</li>\n<li>copied_tracks\n: <a class=\"el\" href=\"structsp__offline__sync__status.html#add0d4345a08fc710614be33c5a662f7c\">sp_offline_sync_status</a>\n</li>\n<li>count\n: <a class=\"el\" href=\"structsp__subscribers.html#a37fd3d0daff9f2d856db1e891ce44bab\">sp_subscribers</a>\n</li>\n<li>credentials_blob_updated\n: <a class=\"el\" href=\"structsp__session__callbacks.html#ae7c5c209735f5c437d76a512eebbf30b\">sp_session_callbacks</a>\n</li>\n</ul>\n\n\n<h3><a class=\"anchor\" id=\"index_d\"></a>- d -</h3><ul>\n<li>description_changed\n: <a class=\"el\" href=\"structsp__playlist__callbacks.html#a07d1ebf29e1ba1f8b10c7a8c5e209f41\">sp_playlist_callbacks</a>\n</li>\n<li>device_id\n: <a class=\"el\" href=\"structsp__session__config.html#af51c373555138dc4012501fa94b2bedc\">sp_session_config</a>\n</li>\n<li>done_tracks\n: <a class=\"el\" href=\"structsp__offline__sync__status.html#aaeb2860d7301485d40d9f0d9bb868fbb\">sp_offline_sync_status</a>\n</li>\n<li>dont_save_metadata_for_playlists\n: <a class=\"el\" href=\"structsp__session__config.html#a190139f3c0842cfe27c61ebf2da5ee9f\">sp_session_config</a>\n</li>\n</ul>\n\n\n<h3><a class=\"anchor\" id=\"index_e\"></a>- e -</h3><ul>\n<li>end_of_track\n: <a class=\"el\" href=\"structsp__session__callbacks.html#a6bc198d89ff46d930c32dae950bd0294\">sp_session_callbacks</a>\n</li>\n<li>error_tracks\n: <a class=\"el\" href=\"structsp__offline__sync__status.html#aa5002b69e3826edc285d19eb7ca0f582\">sp_offline_sync_status</a>\n</li>\n</ul>\n\n\n<h3><a class=\"anchor\" id=\"index_g\"></a>- g -</h3><ul>\n<li>get_audio_buffer_stats\n: <a class=\"el\" href=\"structsp__session__callbacks.html#a328404ac150210387ea3f9cc973149c9\">sp_session_callbacks</a>\n</li>\n</ul>\n\n\n<h3><a class=\"anchor\" id=\"index_i\"></a>- i -</h3><ul>\n<li>image_changed\n: <a class=\"el\" href=\"structsp__playlist__callbacks.html#a910203945dcd26b02b390d5413e4f5dd\">sp_playlist_callbacks</a>\n</li>\n<li>initially_unload_playlists\n: <a class=\"el\" href=\"structsp__session__config.html#a3460b768cf69d1c646ac39f507e39287\">sp_session_config</a>\n</li>\n</ul>\n\n\n<h3><a class=\"anchor\" id=\"index_l\"></a>- l -</h3><ul>\n<li>log_message\n: <a class=\"el\" href=\"structsp__session__callbacks.html#aae0ce9c91f2779fafa40ebd640060a05\">sp_session_callbacks</a>\n</li>\n<li>logged_in\n: <a class=\"el\" href=\"structsp__session__callbacks.html#a52d509962541f7d8fdd71284f40d8415\">sp_session_callbacks</a>\n</li>\n<li>logged_out\n: <a class=\"el\" href=\"structsp__session__callbacks.html#a073231e9ceb3d40f4a772ab64ba4ece7\">sp_session_callbacks</a>\n</li>\n</ul>\n\n\n<h3><a class=\"anchor\" id=\"index_m\"></a>- m -</h3><ul>\n<li>message_to_user\n: <a class=\"el\" href=\"structsp__session__callbacks.html#ae5d6e4a9a4296cfcbca1e57acdb4d64d\">sp_session_callbacks</a>\n</li>\n<li>metadata_updated\n: <a class=\"el\" href=\"structsp__session__callbacks.html#a09912988f00ea5e90835681b382a18fc\">sp_session_callbacks</a>\n</li>\n<li>music_delivery\n: <a class=\"el\" href=\"structsp__session__callbacks.html#a33a31478b8de1882ad7847ad033fbaeb\">sp_session_callbacks</a>\n</li>\n</ul>\n\n\n<h3><a class=\"anchor\" id=\"index_n\"></a>- n -</h3><ul>\n<li>notify_main_thread\n: <a class=\"el\" href=\"structsp__session__callbacks.html#a085cfd82e77aee2b592f314321019a29\">sp_session_callbacks</a>\n</li>\n</ul>\n\n\n<h3><a class=\"anchor\" id=\"index_o\"></a>- o -</h3><ul>\n<li>offline_error\n: <a class=\"el\" href=\"structsp__session__callbacks.html#ad403ac063f5512b277c924add75dfbea\">sp_session_callbacks</a>\n</li>\n<li>offline_status_updated\n: <a class=\"el\" href=\"structsp__session__callbacks.html#aa0f62ed875aab47e5ae093576a6d54c8\">sp_session_callbacks</a>\n</li>\n</ul>\n\n\n<h3><a class=\"anchor\" id=\"index_p\"></a>- p -</h3><ul>\n<li>play_token_lost\n: <a class=\"el\" href=\"structsp__session__callbacks.html#a641fc97950305fbcd83d5114918c53b9\">sp_session_callbacks</a>\n</li>\n<li>playlist_added\n: <a class=\"el\" href=\"structsp__playlistcontainer__callbacks.html#ab1ba98e60fe050aeda8edc95166dd6fe\">sp_playlistcontainer_callbacks</a>\n</li>\n<li>playlist_metadata_updated\n: <a class=\"el\" href=\"structsp__playlist__callbacks.html#a0de3ae5463973647c114d5fdc85ade87\">sp_playlist_callbacks</a>\n</li>\n<li>playlist_moved\n: <a class=\"el\" href=\"structsp__playlistcontainer__callbacks.html#a64889a47ae2023e21be1ca4a8024c663\">sp_playlistcontainer_callbacks</a>\n</li>\n<li>playlist_removed\n: <a class=\"el\" href=\"structsp__playlistcontainer__callbacks.html#ad49b8c0f44f6c05e4ab3562b023f0928\">sp_playlistcontainer_callbacks</a>\n</li>\n<li>playlist_renamed\n: <a class=\"el\" href=\"structsp__playlist__callbacks.html#a25e98e4355cf2d3503c7ac708c8104cf\">sp_playlist_callbacks</a>\n</li>\n<li>playlist_state_changed\n: <a class=\"el\" href=\"structsp__playlist__callbacks.html#a7ff55580625a755b196336a551d210d4\">sp_playlist_callbacks</a>\n</li>\n<li>playlist_update_in_progress\n: <a class=\"el\" href=\"structsp__playlist__callbacks.html#ab07f7eb6c283523afb37d683932b62d4\">sp_playlist_callbacks</a>\n</li>\n<li>private_session_mode_changed\n: <a class=\"el\" href=\"structsp__session__callbacks.html#ad04af396785f8973a3c15a68bb617830\">sp_session_callbacks</a>\n</li>\n<li>proxy\n: <a class=\"el\" href=\"structsp__session__config.html#af7a09f94350796ae7dde15a6518f51e2\">sp_session_config</a>\n</li>\n<li>proxy_password\n: <a class=\"el\" href=\"structsp__session__config.html#a33f2d3aa26d3db999b3026529aa5d670\">sp_session_config</a>\n</li>\n<li>proxy_username\n: <a class=\"el\" href=\"structsp__session__config.html#a393cd7cf64c064f1647fe0045ac0d5cb\">sp_session_config</a>\n</li>\n</ul>\n\n\n<h3><a class=\"anchor\" id=\"index_q\"></a>- q -</h3><ul>\n<li>queued_tracks\n: <a class=\"el\" href=\"structsp__offline__sync__status.html#a44a8a719c66266763ed184b575abce61\">sp_offline_sync_status</a>\n</li>\n</ul>\n\n\n<h3><a class=\"anchor\" id=\"index_s\"></a>- s -</h3><ul>\n<li>sample_rate\n: <a class=\"el\" href=\"structsp__audioformat.html#a2eb66d38a418d5c0afe284d4d45a619d\">sp_audioformat</a>\n</li>\n<li>sample_type\n: <a class=\"el\" href=\"structsp__audioformat.html#af128862563608ee7e41a6d6a4e6133bc\">sp_audioformat</a>\n</li>\n<li>samples\n: <a class=\"el\" href=\"structsp__audio__buffer__stats.html#a1ff9dcc75ace1cc954138fedc4c8f854\">sp_audio_buffer_stats</a>\n</li>\n<li>scrobble_error\n: <a class=\"el\" href=\"structsp__session__callbacks.html#a01a47778439fa233187fdefa75a0f7dc\">sp_session_callbacks</a>\n</li>\n<li>settings_location\n: <a class=\"el\" href=\"structsp__session__config.html#a342532432040d476aaaf73f10893d23b\">sp_session_config</a>\n</li>\n<li>start_playback\n: <a class=\"el\" href=\"structsp__session__callbacks.html#adcfcee6abf1b6f408010e5615d2a79c8\">sp_session_callbacks</a>\n</li>\n<li>stop_playback\n: <a class=\"el\" href=\"structsp__session__callbacks.html#a2a225bc017266c935c05d18142f27ad6\">sp_session_callbacks</a>\n</li>\n<li>streaming_error\n: <a class=\"el\" href=\"structsp__session__callbacks.html#a003db54ec10236a3e3d77bfbf31f38ae\">sp_session_callbacks</a>\n</li>\n<li>stutter\n: <a class=\"el\" href=\"structsp__audio__buffer__stats.html#a85f67e5b11d5ba63b4a94f01a5009d96\">sp_audio_buffer_stats</a>\n</li>\n<li>subscribers\n: <a class=\"el\" href=\"structsp__subscribers.html#aaac89593785dc926976885dfd33efb0c\">sp_subscribers</a>\n</li>\n<li>subscribers_changed\n: <a class=\"el\" href=\"structsp__playlist__callbacks.html#ae33cb7f8ebc9eac186c9f22272d093c3\">sp_playlist_callbacks</a>\n</li>\n<li>syncing\n: <a class=\"el\" href=\"structsp__offline__sync__status.html#a5a2a99fdb8eeb38b3c73a44c6df68d06\">sp_offline_sync_status</a>\n</li>\n</ul>\n\n\n<h3><a class=\"anchor\" id=\"index_t\"></a>- t -</h3><ul>\n<li>tracefile\n: <a class=\"el\" href=\"structsp__session__config.html#aa7df4256deac84eea21053a7ca2cc3da\">sp_session_config</a>\n</li>\n<li>track_created_changed\n: <a class=\"el\" href=\"structsp__playlist__callbacks.html#a152a3b599f22f4040ff0581c6927d12e\">sp_playlist_callbacks</a>\n</li>\n<li>track_message_changed\n: <a class=\"el\" href=\"structsp__playlist__callbacks.html#ad26fb637a16ed0590bdf7936dfcad82d\">sp_playlist_callbacks</a>\n</li>\n<li>track_seen_changed\n: <a class=\"el\" href=\"structsp__playlist__callbacks.html#ab78eaf42523f53bb5931eaff8dcdea8b\">sp_playlist_callbacks</a>\n</li>\n<li>tracks_added\n: <a class=\"el\" href=\"structsp__playlist__callbacks.html#a16c3e5758f8f73f5900de4b88424f85e\">sp_playlist_callbacks</a>\n</li>\n<li>tracks_moved\n: <a class=\"el\" href=\"structsp__playlist__callbacks.html#ac3d51200f7a813cce810561132dba4e9\">sp_playlist_callbacks</a>\n</li>\n<li>tracks_removed\n: <a class=\"el\" href=\"structsp__playlist__callbacks.html#a8f7decf111d725363c968ae4e7b15795\">sp_playlist_callbacks</a>\n</li>\n</ul>\n\n\n<h3><a class=\"anchor\" id=\"index_u\"></a>- u -</h3><ul>\n<li>user_agent\n: <a class=\"el\" href=\"structsp__session__config.html#a69d5b5aa58c901d7916bdea6e5b75c88\">sp_session_config</a>\n</li>\n<li>userdata\n: <a class=\"el\" href=\"structsp__session__config.html#a931b9a253380fdf910afc715e2c2d040\">sp_session_config</a>\n</li>\n<li>userinfo_updated\n: <a class=\"el\" href=\"structsp__session__callbacks.html#a8685310c1755044ec0ea0e316de8be6e\">sp_session_callbacks</a>\n</li>\n</ul>\n\n\n<h3><a class=\"anchor\" id=\"index_w\"></a>- w -</h3><ul>\n<li>willnotcopy_tracks\n: <a class=\"el\" href=\"structsp__offline__sync__status.html#aa56788dbda2c99047cc79282caf3ffd6\">sp_offline_sync_status</a>\n</li>\n</ul>\n</div>\n<hr size=\"1\"><address style=\"text-align: right;\"><small>\nGenerated on Wed Jun 13 2012 14:22:40.<br>\nCopyright &copy; 2006&ndash;2012 Spotify Ltd</small></address>\n</body>\n</html>\n"
  },
  {
    "path": "libspotify/docs/html/functions_vars.html",
    "content": "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\n<html xmlns=\"http://www.w3.org/1999/xhtml\">\n<head>\n<meta http-equiv=\"Content-Type\" content=\"text/xhtml;charset=UTF-8\"/>\n<title>libspotify: Data Fields - Variables</title>\n<link href=\"tabs.css\" rel=\"stylesheet\" type=\"text/css\"/>\n<link href=\"doxygen.css\" rel=\"stylesheet\" type=\"text/css\"/>\n</head>\n<body>\n<!-- Generated by Doxygen 1.7.1 -->\n<div class=\"navigation\" id=\"top\">\n  <div class=\"tabs\">\n    <ul class=\"tablist\">\n      <li><a href=\"index.html\"><span>Main&nbsp;Page</span></a></li>\n      <li><a href=\"modules.html\"><span>Modules</span></a></li>\n      <li class=\"current\"><a href=\"annotated.html\"><span>Data&nbsp;Structures</span></a></li>\n      <li><a href=\"files.html\"><span>Files</span></a></li>\n      <li><a href=\"examples.html\"><span>Examples</span></a></li>\n    </ul>\n  </div>\n  <div class=\"tabs2\">\n    <ul class=\"tablist\">\n      <li><a href=\"annotated.html\"><span>Data&nbsp;Structures</span></a></li>\n      <li class=\"current\"><a href=\"functions.html\"><span>Data&nbsp;Fields</span></a></li>\n    </ul>\n  </div>\n  <div class=\"tabs2\">\n    <ul class=\"tablist\">\n      <li><a href=\"functions.html\"><span>All</span></a></li>\n      <li class=\"current\"><a href=\"functions_vars.html\"><span>Variables</span></a></li>\n    </ul>\n  </div>\n  <div class=\"tabs3\">\n    <ul class=\"tablist\">\n      <li><a href=\"#index_a\"><span>a</span></a></li>\n      <li><a href=\"#index_c\"><span>c</span></a></li>\n      <li><a href=\"#index_d\"><span>d</span></a></li>\n      <li><a href=\"#index_e\"><span>e</span></a></li>\n      <li><a href=\"#index_g\"><span>g</span></a></li>\n      <li><a href=\"#index_i\"><span>i</span></a></li>\n      <li><a href=\"#index_l\"><span>l</span></a></li>\n      <li><a href=\"#index_m\"><span>m</span></a></li>\n      <li><a href=\"#index_n\"><span>n</span></a></li>\n      <li><a href=\"#index_o\"><span>o</span></a></li>\n      <li><a href=\"#index_p\"><span>p</span></a></li>\n      <li><a href=\"#index_q\"><span>q</span></a></li>\n      <li><a href=\"#index_s\"><span>s</span></a></li>\n      <li><a href=\"#index_t\"><span>t</span></a></li>\n      <li><a href=\"#index_u\"><span>u</span></a></li>\n      <li><a href=\"#index_w\"><span>w</span></a></li>\n    </ul>\n  </div>\n</div>\n<div class=\"contents\">\n&nbsp;\n\n<h3><a class=\"anchor\" id=\"index_a\"></a>- a -</h3><ul>\n<li>api_version\n: <a class=\"el\" href=\"structsp__session__config.html#a1ed9d4ff26e6f666ba96dce41d5f1bac\">sp_session_config</a>\n</li>\n<li>application_key\n: <a class=\"el\" href=\"structsp__session__config.html#ab5a5296a8e34bb454e7575940a19b9ae\">sp_session_config</a>\n</li>\n<li>application_key_size\n: <a class=\"el\" href=\"structsp__session__config.html#ab10b332fe29b941162fd1d9ea1003b82\">sp_session_config</a>\n</li>\n</ul>\n\n\n<h3><a class=\"anchor\" id=\"index_c\"></a>- c -</h3><ul>\n<li>ca_certs_filename\n: <a class=\"el\" href=\"structsp__session__config.html#a4a94ad4270e5401e68587952661bd3ca\">sp_session_config</a>\n</li>\n<li>cache_location\n: <a class=\"el\" href=\"structsp__session__config.html#ad1cb5e3670451d8cee3d8c9766b523fc\">sp_session_config</a>\n</li>\n<li>callbacks\n: <a class=\"el\" href=\"structsp__session__config.html#af0b456e6b9228ed812cd8ad28acbb127\">sp_session_config</a>\n</li>\n<li>channels\n: <a class=\"el\" href=\"structsp__audioformat.html#ab6b47d8d0ebfaab73229d707dc8bf0b8\">sp_audioformat</a>\n</li>\n<li>compress_playlists\n: <a class=\"el\" href=\"structsp__session__config.html#a8413a38bf3db9047b45525ac5dd4bc7b\">sp_session_config</a>\n</li>\n<li>connection_error\n: <a class=\"el\" href=\"structsp__session__callbacks.html#a45bf5d3fac7953099a191ea39fcfc018\">sp_session_callbacks</a>\n</li>\n<li>connectionstate_updated\n: <a class=\"el\" href=\"structsp__session__callbacks.html#a379c96577e927d6c65ac61fe13c1e412\">sp_session_callbacks</a>\n</li>\n<li>container_loaded\n: <a class=\"el\" href=\"structsp__playlistcontainer__callbacks.html#a8a0c301dd9cf90cccb4657a7d65c61b1\">sp_playlistcontainer_callbacks</a>\n</li>\n<li>copied_tracks\n: <a class=\"el\" href=\"structsp__offline__sync__status.html#add0d4345a08fc710614be33c5a662f7c\">sp_offline_sync_status</a>\n</li>\n<li>count\n: <a class=\"el\" href=\"structsp__subscribers.html#a37fd3d0daff9f2d856db1e891ce44bab\">sp_subscribers</a>\n</li>\n<li>credentials_blob_updated\n: <a class=\"el\" href=\"structsp__session__callbacks.html#ae7c5c209735f5c437d76a512eebbf30b\">sp_session_callbacks</a>\n</li>\n</ul>\n\n\n<h3><a class=\"anchor\" id=\"index_d\"></a>- d -</h3><ul>\n<li>description_changed\n: <a class=\"el\" href=\"structsp__playlist__callbacks.html#a07d1ebf29e1ba1f8b10c7a8c5e209f41\">sp_playlist_callbacks</a>\n</li>\n<li>device_id\n: <a class=\"el\" href=\"structsp__session__config.html#af51c373555138dc4012501fa94b2bedc\">sp_session_config</a>\n</li>\n<li>done_tracks\n: <a class=\"el\" href=\"structsp__offline__sync__status.html#aaeb2860d7301485d40d9f0d9bb868fbb\">sp_offline_sync_status</a>\n</li>\n<li>dont_save_metadata_for_playlists\n: <a class=\"el\" href=\"structsp__session__config.html#a190139f3c0842cfe27c61ebf2da5ee9f\">sp_session_config</a>\n</li>\n</ul>\n\n\n<h3><a class=\"anchor\" id=\"index_e\"></a>- e -</h3><ul>\n<li>end_of_track\n: <a class=\"el\" href=\"structsp__session__callbacks.html#a6bc198d89ff46d930c32dae950bd0294\">sp_session_callbacks</a>\n</li>\n<li>error_tracks\n: <a class=\"el\" href=\"structsp__offline__sync__status.html#aa5002b69e3826edc285d19eb7ca0f582\">sp_offline_sync_status</a>\n</li>\n</ul>\n\n\n<h3><a class=\"anchor\" id=\"index_g\"></a>- g -</h3><ul>\n<li>get_audio_buffer_stats\n: <a class=\"el\" href=\"structsp__session__callbacks.html#a328404ac150210387ea3f9cc973149c9\">sp_session_callbacks</a>\n</li>\n</ul>\n\n\n<h3><a class=\"anchor\" id=\"index_i\"></a>- i -</h3><ul>\n<li>image_changed\n: <a class=\"el\" href=\"structsp__playlist__callbacks.html#a910203945dcd26b02b390d5413e4f5dd\">sp_playlist_callbacks</a>\n</li>\n<li>initially_unload_playlists\n: <a class=\"el\" href=\"structsp__session__config.html#a3460b768cf69d1c646ac39f507e39287\">sp_session_config</a>\n</li>\n</ul>\n\n\n<h3><a class=\"anchor\" id=\"index_l\"></a>- l -</h3><ul>\n<li>log_message\n: <a class=\"el\" href=\"structsp__session__callbacks.html#aae0ce9c91f2779fafa40ebd640060a05\">sp_session_callbacks</a>\n</li>\n<li>logged_in\n: <a class=\"el\" href=\"structsp__session__callbacks.html#a52d509962541f7d8fdd71284f40d8415\">sp_session_callbacks</a>\n</li>\n<li>logged_out\n: <a class=\"el\" href=\"structsp__session__callbacks.html#a073231e9ceb3d40f4a772ab64ba4ece7\">sp_session_callbacks</a>\n</li>\n</ul>\n\n\n<h3><a class=\"anchor\" id=\"index_m\"></a>- m -</h3><ul>\n<li>message_to_user\n: <a class=\"el\" href=\"structsp__session__callbacks.html#ae5d6e4a9a4296cfcbca1e57acdb4d64d\">sp_session_callbacks</a>\n</li>\n<li>metadata_updated\n: <a class=\"el\" href=\"structsp__session__callbacks.html#a09912988f00ea5e90835681b382a18fc\">sp_session_callbacks</a>\n</li>\n<li>music_delivery\n: <a class=\"el\" href=\"structsp__session__callbacks.html#a33a31478b8de1882ad7847ad033fbaeb\">sp_session_callbacks</a>\n</li>\n</ul>\n\n\n<h3><a class=\"anchor\" id=\"index_n\"></a>- n -</h3><ul>\n<li>notify_main_thread\n: <a class=\"el\" href=\"structsp__session__callbacks.html#a085cfd82e77aee2b592f314321019a29\">sp_session_callbacks</a>\n</li>\n</ul>\n\n\n<h3><a class=\"anchor\" id=\"index_o\"></a>- o -</h3><ul>\n<li>offline_error\n: <a class=\"el\" href=\"structsp__session__callbacks.html#ad403ac063f5512b277c924add75dfbea\">sp_session_callbacks</a>\n</li>\n<li>offline_status_updated\n: <a class=\"el\" href=\"structsp__session__callbacks.html#aa0f62ed875aab47e5ae093576a6d54c8\">sp_session_callbacks</a>\n</li>\n</ul>\n\n\n<h3><a class=\"anchor\" id=\"index_p\"></a>- p -</h3><ul>\n<li>play_token_lost\n: <a class=\"el\" href=\"structsp__session__callbacks.html#a641fc97950305fbcd83d5114918c53b9\">sp_session_callbacks</a>\n</li>\n<li>playlist_added\n: <a class=\"el\" href=\"structsp__playlistcontainer__callbacks.html#ab1ba98e60fe050aeda8edc95166dd6fe\">sp_playlistcontainer_callbacks</a>\n</li>\n<li>playlist_metadata_updated\n: <a class=\"el\" href=\"structsp__playlist__callbacks.html#a0de3ae5463973647c114d5fdc85ade87\">sp_playlist_callbacks</a>\n</li>\n<li>playlist_moved\n: <a class=\"el\" href=\"structsp__playlistcontainer__callbacks.html#a64889a47ae2023e21be1ca4a8024c663\">sp_playlistcontainer_callbacks</a>\n</li>\n<li>playlist_removed\n: <a class=\"el\" href=\"structsp__playlistcontainer__callbacks.html#ad49b8c0f44f6c05e4ab3562b023f0928\">sp_playlistcontainer_callbacks</a>\n</li>\n<li>playlist_renamed\n: <a class=\"el\" href=\"structsp__playlist__callbacks.html#a25e98e4355cf2d3503c7ac708c8104cf\">sp_playlist_callbacks</a>\n</li>\n<li>playlist_state_changed\n: <a class=\"el\" href=\"structsp__playlist__callbacks.html#a7ff55580625a755b196336a551d210d4\">sp_playlist_callbacks</a>\n</li>\n<li>playlist_update_in_progress\n: <a class=\"el\" href=\"structsp__playlist__callbacks.html#ab07f7eb6c283523afb37d683932b62d4\">sp_playlist_callbacks</a>\n</li>\n<li>private_session_mode_changed\n: <a class=\"el\" href=\"structsp__session__callbacks.html#ad04af396785f8973a3c15a68bb617830\">sp_session_callbacks</a>\n</li>\n<li>proxy\n: <a class=\"el\" href=\"structsp__session__config.html#af7a09f94350796ae7dde15a6518f51e2\">sp_session_config</a>\n</li>\n<li>proxy_password\n: <a class=\"el\" href=\"structsp__session__config.html#a33f2d3aa26d3db999b3026529aa5d670\">sp_session_config</a>\n</li>\n<li>proxy_username\n: <a class=\"el\" href=\"structsp__session__config.html#a393cd7cf64c064f1647fe0045ac0d5cb\">sp_session_config</a>\n</li>\n</ul>\n\n\n<h3><a class=\"anchor\" id=\"index_q\"></a>- q -</h3><ul>\n<li>queued_tracks\n: <a class=\"el\" href=\"structsp__offline__sync__status.html#a44a8a719c66266763ed184b575abce61\">sp_offline_sync_status</a>\n</li>\n</ul>\n\n\n<h3><a class=\"anchor\" id=\"index_s\"></a>- s -</h3><ul>\n<li>sample_rate\n: <a class=\"el\" href=\"structsp__audioformat.html#a2eb66d38a418d5c0afe284d4d45a619d\">sp_audioformat</a>\n</li>\n<li>sample_type\n: <a class=\"el\" href=\"structsp__audioformat.html#af128862563608ee7e41a6d6a4e6133bc\">sp_audioformat</a>\n</li>\n<li>samples\n: <a class=\"el\" href=\"structsp__audio__buffer__stats.html#a1ff9dcc75ace1cc954138fedc4c8f854\">sp_audio_buffer_stats</a>\n</li>\n<li>scrobble_error\n: <a class=\"el\" href=\"structsp__session__callbacks.html#a01a47778439fa233187fdefa75a0f7dc\">sp_session_callbacks</a>\n</li>\n<li>settings_location\n: <a class=\"el\" href=\"structsp__session__config.html#a342532432040d476aaaf73f10893d23b\">sp_session_config</a>\n</li>\n<li>start_playback\n: <a class=\"el\" href=\"structsp__session__callbacks.html#adcfcee6abf1b6f408010e5615d2a79c8\">sp_session_callbacks</a>\n</li>\n<li>stop_playback\n: <a class=\"el\" href=\"structsp__session__callbacks.html#a2a225bc017266c935c05d18142f27ad6\">sp_session_callbacks</a>\n</li>\n<li>streaming_error\n: <a class=\"el\" href=\"structsp__session__callbacks.html#a003db54ec10236a3e3d77bfbf31f38ae\">sp_session_callbacks</a>\n</li>\n<li>stutter\n: <a class=\"el\" href=\"structsp__audio__buffer__stats.html#a85f67e5b11d5ba63b4a94f01a5009d96\">sp_audio_buffer_stats</a>\n</li>\n<li>subscribers\n: <a class=\"el\" href=\"structsp__subscribers.html#aaac89593785dc926976885dfd33efb0c\">sp_subscribers</a>\n</li>\n<li>subscribers_changed\n: <a class=\"el\" href=\"structsp__playlist__callbacks.html#ae33cb7f8ebc9eac186c9f22272d093c3\">sp_playlist_callbacks</a>\n</li>\n<li>syncing\n: <a class=\"el\" href=\"structsp__offline__sync__status.html#a5a2a99fdb8eeb38b3c73a44c6df68d06\">sp_offline_sync_status</a>\n</li>\n</ul>\n\n\n<h3><a class=\"anchor\" id=\"index_t\"></a>- t -</h3><ul>\n<li>tracefile\n: <a class=\"el\" href=\"structsp__session__config.html#aa7df4256deac84eea21053a7ca2cc3da\">sp_session_config</a>\n</li>\n<li>track_created_changed\n: <a class=\"el\" href=\"structsp__playlist__callbacks.html#a152a3b599f22f4040ff0581c6927d12e\">sp_playlist_callbacks</a>\n</li>\n<li>track_message_changed\n: <a class=\"el\" href=\"structsp__playlist__callbacks.html#ad26fb637a16ed0590bdf7936dfcad82d\">sp_playlist_callbacks</a>\n</li>\n<li>track_seen_changed\n: <a class=\"el\" href=\"structsp__playlist__callbacks.html#ab78eaf42523f53bb5931eaff8dcdea8b\">sp_playlist_callbacks</a>\n</li>\n<li>tracks_added\n: <a class=\"el\" href=\"structsp__playlist__callbacks.html#a16c3e5758f8f73f5900de4b88424f85e\">sp_playlist_callbacks</a>\n</li>\n<li>tracks_moved\n: <a class=\"el\" href=\"structsp__playlist__callbacks.html#ac3d51200f7a813cce810561132dba4e9\">sp_playlist_callbacks</a>\n</li>\n<li>tracks_removed\n: <a class=\"el\" href=\"structsp__playlist__callbacks.html#a8f7decf111d725363c968ae4e7b15795\">sp_playlist_callbacks</a>\n</li>\n</ul>\n\n\n<h3><a class=\"anchor\" id=\"index_u\"></a>- u -</h3><ul>\n<li>user_agent\n: <a class=\"el\" href=\"structsp__session__config.html#a69d5b5aa58c901d7916bdea6e5b75c88\">sp_session_config</a>\n</li>\n<li>userdata\n: <a class=\"el\" href=\"structsp__session__config.html#a931b9a253380fdf910afc715e2c2d040\">sp_session_config</a>\n</li>\n<li>userinfo_updated\n: <a class=\"el\" href=\"structsp__session__callbacks.html#a8685310c1755044ec0ea0e316de8be6e\">sp_session_callbacks</a>\n</li>\n</ul>\n\n\n<h3><a class=\"anchor\" id=\"index_w\"></a>- w -</h3><ul>\n<li>willnotcopy_tracks\n: <a class=\"el\" href=\"structsp__offline__sync__status.html#aa56788dbda2c99047cc79282caf3ffd6\">sp_offline_sync_status</a>\n</li>\n</ul>\n</div>\n<hr size=\"1\"><address style=\"text-align: right;\"><small>\nGenerated on Wed Jun 13 2012 14:22:40.<br>\nCopyright &copy; 2006&ndash;2012 Spotify Ltd</small></address>\n</body>\n</html>\n"
  },
  {
    "path": "libspotify/docs/html/globals.html",
    "content": "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\n<html xmlns=\"http://www.w3.org/1999/xhtml\">\n<head>\n<meta http-equiv=\"Content-Type\" content=\"text/xhtml;charset=UTF-8\"/>\n<title>libspotify: Data Fields</title>\n<link href=\"tabs.css\" rel=\"stylesheet\" type=\"text/css\"/>\n<link href=\"doxygen.css\" rel=\"stylesheet\" type=\"text/css\"/>\n</head>\n<body>\n<!-- Generated by Doxygen 1.7.1 -->\n<div class=\"navigation\" id=\"top\">\n  <div class=\"tabs\">\n    <ul class=\"tablist\">\n      <li><a href=\"index.html\"><span>Main&nbsp;Page</span></a></li>\n      <li><a href=\"modules.html\"><span>Modules</span></a></li>\n      <li><a href=\"annotated.html\"><span>Data&nbsp;Structures</span></a></li>\n      <li class=\"current\"><a href=\"files.html\"><span>Files</span></a></li>\n      <li><a href=\"examples.html\"><span>Examples</span></a></li>\n    </ul>\n  </div>\n  <div class=\"tabs2\">\n    <ul class=\"tablist\">\n      <li><a href=\"files.html\"><span>File&nbsp;List</span></a></li>\n      <li class=\"current\"><a href=\"globals.html\"><span>Globals</span></a></li>\n    </ul>\n  </div>\n  <div class=\"tabs2\">\n    <ul class=\"tablist\">\n      <li class=\"current\"><a href=\"globals.html\"><span>All</span></a></li>\n      <li><a href=\"globals_func.html\"><span>Functions</span></a></li>\n      <li><a href=\"globals_type.html\"><span>Typedefs</span></a></li>\n      <li><a href=\"globals_enum.html\"><span>Enumerations</span></a></li>\n      <li><a href=\"globals_eval.html\"><span>Enumerator</span></a></li>\n      <li><a href=\"globals_defs.html\"><span>Defines</span></a></li>\n    </ul>\n  </div>\n  <div class=\"tabs3\">\n    <ul class=\"tablist\">\n      <li class=\"current\"><a href=\"globals.html#index_a\"><span>a</span></a></li>\n      <li><a href=\"globals_0x69.html#index_i\"><span>i</span></a></li>\n      <li><a href=\"globals_0x73.html#index_s\"><span>s</span></a></li>\n      <li><a href=\"globals_0x74.html#index_t\"><span>t</span></a></li>\n    </ul>\n  </div>\n</div>\n<div class=\"contents\">\nHere is a list of all documented functions, variables, defines, enums, and typedefs with links to the documentation:\n\n<h3><a class=\"anchor\" id=\"index_a\"></a>- a -</h3><ul>\n<li>albumbrowse_complete_cb\n: <a class=\"el\" href=\"group__albumbrowse.html#gabd76254f89048e6d368929015a0c739f\">api.h</a>\n</li>\n<li>artistbrowse_complete_cb\n: <a class=\"el\" href=\"group__artistbrowse.html#ga8077aa18c043210e859479be2616a3e7\">api.h</a>\n</li>\n</ul>\n</div>\n<hr size=\"1\"><address style=\"text-align: right;\"><small>\nGenerated on Wed Jun 13 2012 14:22:40.<br>\nCopyright &copy; 2006&ndash;2012 Spotify Ltd</small></address>\n</body>\n</html>\n"
  },
  {
    "path": "libspotify/docs/html/globals_0x69.html",
    "content": "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\n<html xmlns=\"http://www.w3.org/1999/xhtml\">\n<head>\n<meta http-equiv=\"Content-Type\" content=\"text/xhtml;charset=UTF-8\"/>\n<title>libspotify: Data Fields</title>\n<link href=\"tabs.css\" rel=\"stylesheet\" type=\"text/css\"/>\n<link href=\"doxygen.css\" rel=\"stylesheet\" type=\"text/css\"/>\n</head>\n<body>\n<!-- Generated by Doxygen 1.7.1 -->\n<div class=\"navigation\" id=\"top\">\n  <div class=\"tabs\">\n    <ul class=\"tablist\">\n      <li><a href=\"index.html\"><span>Main&nbsp;Page</span></a></li>\n      <li><a href=\"modules.html\"><span>Modules</span></a></li>\n      <li><a href=\"annotated.html\"><span>Data&nbsp;Structures</span></a></li>\n      <li class=\"current\"><a href=\"files.html\"><span>Files</span></a></li>\n      <li><a href=\"examples.html\"><span>Examples</span></a></li>\n    </ul>\n  </div>\n  <div class=\"tabs2\">\n    <ul class=\"tablist\">\n      <li><a href=\"files.html\"><span>File&nbsp;List</span></a></li>\n      <li class=\"current\"><a href=\"globals.html\"><span>Globals</span></a></li>\n    </ul>\n  </div>\n  <div class=\"tabs2\">\n    <ul class=\"tablist\">\n      <li class=\"current\"><a href=\"globals.html\"><span>All</span></a></li>\n      <li><a href=\"globals_func.html\"><span>Functions</span></a></li>\n      <li><a href=\"globals_type.html\"><span>Typedefs</span></a></li>\n      <li><a href=\"globals_enum.html\"><span>Enumerations</span></a></li>\n      <li><a href=\"globals_eval.html\"><span>Enumerator</span></a></li>\n      <li><a href=\"globals_defs.html\"><span>Defines</span></a></li>\n    </ul>\n  </div>\n  <div class=\"tabs3\">\n    <ul class=\"tablist\">\n      <li><a href=\"globals.html#index_a\"><span>a</span></a></li>\n      <li class=\"current\"><a href=\"globals_0x69.html#index_i\"><span>i</span></a></li>\n      <li><a href=\"globals_0x73.html#index_s\"><span>s</span></a></li>\n      <li><a href=\"globals_0x74.html#index_t\"><span>t</span></a></li>\n    </ul>\n  </div>\n</div>\n<div class=\"contents\">\nHere is a list of all documented functions, variables, defines, enums, and typedefs with links to the documentation:\n\n<h3><a class=\"anchor\" id=\"index_i\"></a>- i -</h3><ul>\n<li>image_loaded_cb\n: <a class=\"el\" href=\"group__image.html#ga713bef7c5dedba7d91b9710cd9b5faa4\">api.h</a>\n</li>\n<li>inboxpost_complete_cb\n: <a class=\"el\" href=\"group__inbox.html#ga5084d6ab753294730402a0c43b82e60c\">api.h</a>\n</li>\n</ul>\n</div>\n<hr size=\"1\"><address style=\"text-align: right;\"><small>\nGenerated on Wed Jun 13 2012 14:22:40.<br>\nCopyright &copy; 2006&ndash;2012 Spotify Ltd</small></address>\n</body>\n</html>\n"
  },
  {
    "path": "libspotify/docs/html/globals_0x73.html",
    "content": "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\n<html xmlns=\"http://www.w3.org/1999/xhtml\">\n<head>\n<meta http-equiv=\"Content-Type\" content=\"text/xhtml;charset=UTF-8\"/>\n<title>libspotify: Data Fields</title>\n<link href=\"tabs.css\" rel=\"stylesheet\" type=\"text/css\"/>\n<link href=\"doxygen.css\" rel=\"stylesheet\" type=\"text/css\"/>\n</head>\n<body>\n<!-- Generated by Doxygen 1.7.1 -->\n<div class=\"navigation\" id=\"top\">\n  <div class=\"tabs\">\n    <ul class=\"tablist\">\n      <li><a href=\"index.html\"><span>Main&nbsp;Page</span></a></li>\n      <li><a href=\"modules.html\"><span>Modules</span></a></li>\n      <li><a href=\"annotated.html\"><span>Data&nbsp;Structures</span></a></li>\n      <li class=\"current\"><a href=\"files.html\"><span>Files</span></a></li>\n      <li><a href=\"examples.html\"><span>Examples</span></a></li>\n    </ul>\n  </div>\n  <div class=\"tabs2\">\n    <ul class=\"tablist\">\n      <li><a href=\"files.html\"><span>File&nbsp;List</span></a></li>\n      <li class=\"current\"><a href=\"globals.html\"><span>Globals</span></a></li>\n    </ul>\n  </div>\n  <div class=\"tabs2\">\n    <ul class=\"tablist\">\n      <li class=\"current\"><a href=\"globals.html\"><span>All</span></a></li>\n      <li><a href=\"globals_func.html\"><span>Functions</span></a></li>\n      <li><a href=\"globals_type.html\"><span>Typedefs</span></a></li>\n      <li><a href=\"globals_enum.html\"><span>Enumerations</span></a></li>\n      <li><a href=\"globals_eval.html\"><span>Enumerator</span></a></li>\n      <li><a href=\"globals_defs.html\"><span>Defines</span></a></li>\n    </ul>\n  </div>\n  <div class=\"tabs3\">\n    <ul class=\"tablist\">\n      <li><a href=\"globals.html#index_a\"><span>a</span></a></li>\n      <li><a href=\"globals_0x69.html#index_i\"><span>i</span></a></li>\n      <li class=\"current\"><a href=\"globals_0x73.html#index_s\"><span>s</span></a></li>\n      <li><a href=\"globals_0x74.html#index_t\"><span>t</span></a></li>\n    </ul>\n  </div>\n</div>\n<div class=\"contents\">\nHere is a list of all documented functions, variables, defines, enums, and typedefs with links to the documentation:\n\n<h3><a class=\"anchor\" id=\"index_s\"></a>- s -</h3><ul>\n<li>search_complete_cb\n: <a class=\"el\" href=\"group__search.html#gabcd51c99a318b9f36dfe2948d8209bb1\">api.h</a>\n</li>\n<li>sp_album\n: <a class=\"el\" href=\"group__types.html#ga6fd3e5de729c429fef3ff18ece6dcfad\">api.h</a>\n</li>\n<li>sp_album_add_ref()\n: <a class=\"el\" href=\"group__album.html#ga08192dd38d1c628f7b51615fffa33017\">api.h</a>\n</li>\n<li>sp_album_artist()\n: <a class=\"el\" href=\"group__album.html#ga42309972141dab10c32d741d357c01de\">api.h</a>\n</li>\n<li>sp_album_cover()\n: <a class=\"el\" href=\"group__album.html#ga6616ef3df724af185c5eb58e8a0fb808\">api.h</a>\n</li>\n<li>sp_album_is_available()\n: <a class=\"el\" href=\"group__album.html#ga89eb8dc73a76f5e0509b1066426495f7\">api.h</a>\n</li>\n<li>sp_album_is_loaded()\n: <a class=\"el\" href=\"group__album.html#ga46fbfa98be12c2f4067d5e679552cfb9\">api.h</a>\n</li>\n<li>sp_album_name()\n: <a class=\"el\" href=\"group__album.html#ga0e828c991a8184d60026513f944e19ad\">api.h</a>\n</li>\n<li>sp_album_release()\n: <a class=\"el\" href=\"group__album.html#ga5c6e49d04ffb05c722db5e78c9434b88\">api.h</a>\n</li>\n<li>sp_album_type()\n: <a class=\"el\" href=\"group__album.html#ga8dceb04a62bdb3ffc112ed0efc359e51\">api.h</a>\n</li>\n<li>sp_album_year()\n: <a class=\"el\" href=\"group__album.html#ga2aadf934b0af43c3ef6ee98b6a8065fd\">api.h</a>\n</li>\n<li>sp_albumbrowse\n: <a class=\"el\" href=\"group__types.html#ga9c4550473a7a07790778ba870c31b4d9\">api.h</a>\n</li>\n<li>sp_albumbrowse_add_ref()\n: <a class=\"el\" href=\"group__albumbrowse.html#ga1afd6a10febf31a61cf356673cb34bef\">api.h</a>\n</li>\n<li>sp_albumbrowse_album()\n: <a class=\"el\" href=\"group__albumbrowse.html#gaf0dadfc4edb48a3558b606e30e8bedfa\">api.h</a>\n</li>\n<li>sp_albumbrowse_artist()\n: <a class=\"el\" href=\"group__albumbrowse.html#ga4f835537a65bcac9ec52cef1058a44bc\">api.h</a>\n</li>\n<li>sp_albumbrowse_backend_request_duration()\n: <a class=\"el\" href=\"group__albumbrowse.html#ga2f1e1049065e8c090c010f8e43061bd4\">api.h</a>\n</li>\n<li>sp_albumbrowse_copyright()\n: <a class=\"el\" href=\"group__albumbrowse.html#ga34b205daa2960e8d02a6e1accd80ab92\">api.h</a>\n</li>\n<li>sp_albumbrowse_create()\n: <a class=\"el\" href=\"group__albumbrowse.html#gaf1bc3042e748efea5ca7ac159e5cbfbe\">api.h</a>\n</li>\n<li>sp_albumbrowse_error()\n: <a class=\"el\" href=\"group__albumbrowse.html#ga153417eee319e7711b66503f88fba88b\">api.h</a>\n</li>\n<li>sp_albumbrowse_is_loaded()\n: <a class=\"el\" href=\"group__albumbrowse.html#gad618d2752eb55173ab373d1407971960\">api.h</a>\n</li>\n<li>sp_albumbrowse_num_copyrights()\n: <a class=\"el\" href=\"group__albumbrowse.html#gab53fa74ee1958dad5186be09e70ddc4a\">api.h</a>\n</li>\n<li>sp_albumbrowse_num_tracks()\n: <a class=\"el\" href=\"group__albumbrowse.html#ga3fb91de745ca07d3801a57288f2d9da7\">api.h</a>\n</li>\n<li>sp_albumbrowse_release()\n: <a class=\"el\" href=\"group__albumbrowse.html#gabdd5a4e3b2098166b67e35979f59613d\">api.h</a>\n</li>\n<li>sp_albumbrowse_review()\n: <a class=\"el\" href=\"group__albumbrowse.html#ga868f3f3263f5033ae1fba60f403be712\">api.h</a>\n</li>\n<li>sp_albumbrowse_track()\n: <a class=\"el\" href=\"group__albumbrowse.html#gad3c8df4b75158bba2c06aaefa74c5aa1\">api.h</a>\n</li>\n<li>sp_albumtype\n: <a class=\"el\" href=\"group__album.html#ga019b49a9d1633b61daa79c80ea01d5c3\">api.h</a>\n</li>\n<li>SP_ALBUMTYPE_ALBUM\n: <a class=\"el\" href=\"group__album.html#gga019b49a9d1633b61daa79c80ea01d5c3ad1693d93a2c05c053fc4fd77886af8dd\">api.h</a>\n</li>\n<li>SP_ALBUMTYPE_COMPILATION\n: <a class=\"el\" href=\"group__album.html#gga019b49a9d1633b61daa79c80ea01d5c3a8fee6ba46e8876037f4f2e46c6d6c6af\">api.h</a>\n</li>\n<li>SP_ALBUMTYPE_SINGLE\n: <a class=\"el\" href=\"group__album.html#gga019b49a9d1633b61daa79c80ea01d5c3a3b6f78b733f1bc18a5e4fa18c020fc73\">api.h</a>\n</li>\n<li>SP_ALBUMTYPE_UNKNOWN\n: <a class=\"el\" href=\"group__album.html#gga019b49a9d1633b61daa79c80ea01d5c3ad564ed5f1f0659929fe5ec700513873f\">api.h</a>\n</li>\n<li>sp_artist\n: <a class=\"el\" href=\"group__types.html#ga31764fbd69618c10be173c6c03d4c1bc\">api.h</a>\n</li>\n<li>sp_artist_add_ref()\n: <a class=\"el\" href=\"group__artist.html#gac70d7467f580aa497d1a5d610e06d273\">api.h</a>\n</li>\n<li>sp_artist_is_loaded()\n: <a class=\"el\" href=\"group__artist.html#gafc98f5093184a7ac7ce608302b0971ea\">api.h</a>\n</li>\n<li>sp_artist_name()\n: <a class=\"el\" href=\"group__artist.html#gad2895555bb48514986823733a7afe5e2\">api.h</a>\n</li>\n<li>sp_artist_portrait()\n: <a class=\"el\" href=\"group__artist.html#ga87d366ac7479c717005c2c059d5f2be9\">api.h</a>\n</li>\n<li>sp_artist_release()\n: <a class=\"el\" href=\"group__artist.html#ga7b0da8f7ce09454bd0821d06d52e2d12\">api.h</a>\n</li>\n<li>sp_artistbrowse\n: <a class=\"el\" href=\"group__types.html#gafd3d5aae485f1012ec91b7948e6f9f2b\">api.h</a>\n</li>\n<li>sp_artistbrowse_add_ref()\n: <a class=\"el\" href=\"group__artistbrowse.html#ga69fc2e1d2d5e8d91a724486cbfd0c4dc\">api.h</a>\n</li>\n<li>sp_artistbrowse_album()\n: <a class=\"el\" href=\"group__artistbrowse.html#ga5b36c9a34876beea8fda8674b93d4fd3\">api.h</a>\n</li>\n<li>sp_artistbrowse_artist()\n: <a class=\"el\" href=\"group__artistbrowse.html#ga5f6a046b2bd261d7628582b986a9019f\">api.h</a>\n</li>\n<li>sp_artistbrowse_backend_request_duration()\n: <a class=\"el\" href=\"group__artistbrowse.html#gadce357748b82abce8a7b093882850fdb\">api.h</a>\n</li>\n<li>sp_artistbrowse_biography()\n: <a class=\"el\" href=\"group__artistbrowse.html#ga8b93b9e5630662855f35694280ba4d2b\">api.h</a>\n</li>\n<li>sp_artistbrowse_create()\n: <a class=\"el\" href=\"group__artistbrowse.html#ga8dd8364b2fcd29c846209660bd9a69b2\">api.h</a>\n</li>\n<li>sp_artistbrowse_error()\n: <a class=\"el\" href=\"group__artistbrowse.html#ga203e757088ff7a5098f16a1367da25d2\">api.h</a>\n</li>\n<li>SP_ARTISTBROWSE_FULL\n: <a class=\"el\" href=\"group__session.html#ggac86504cc9e8cadbc30c8aa8dbf355034a2914168528aded818177c013a0dd7e87\">api.h</a>\n</li>\n<li>sp_artistbrowse_is_loaded()\n: <a class=\"el\" href=\"group__artistbrowse.html#ga966b0f59e7b2b3d0037e44bb49dcdabc\">api.h</a>\n</li>\n<li>SP_ARTISTBROWSE_NO_ALBUMS\n: <a class=\"el\" href=\"group__session.html#ggac86504cc9e8cadbc30c8aa8dbf355034ac0032981f8dbf44c022e6a7ab1672167\">api.h</a>\n</li>\n<li>SP_ARTISTBROWSE_NO_TRACKS\n: <a class=\"el\" href=\"group__session.html#ggac86504cc9e8cadbc30c8aa8dbf355034afbad1e58606b3230dce5bc3320c95d12\">api.h</a>\n</li>\n<li>sp_artistbrowse_num_albums()\n: <a class=\"el\" href=\"group__artistbrowse.html#gaf0055361abd53425d89a4636a32b5c83\">api.h</a>\n</li>\n<li>sp_artistbrowse_num_portraits()\n: <a class=\"el\" href=\"group__artistbrowse.html#ga98dc47d36d2789999bfe62707c5041d7\">api.h</a>\n</li>\n<li>sp_artistbrowse_num_similar_artists()\n: <a class=\"el\" href=\"group__artistbrowse.html#ga2559638742416ac621af0e919e017d17\">api.h</a>\n</li>\n<li>sp_artistbrowse_num_tophit_tracks()\n: <a class=\"el\" href=\"group__artistbrowse.html#ga0c26782796af954300ce92fddea97637\">api.h</a>\n</li>\n<li>sp_artistbrowse_num_tracks()\n: <a class=\"el\" href=\"group__artistbrowse.html#ga8c862caa2234125ffcc4e93287b1e029\">api.h</a>\n</li>\n<li>sp_artistbrowse_portrait()\n: <a class=\"el\" href=\"group__artistbrowse.html#ga5f164b2f9609a7bf2c89b3a1407ec239\">api.h</a>\n</li>\n<li>sp_artistbrowse_release()\n: <a class=\"el\" href=\"group__artistbrowse.html#ga14626a4f6a60b1caf61cb54c26783671\">api.h</a>\n</li>\n<li>sp_artistbrowse_similar_artist()\n: <a class=\"el\" href=\"group__artistbrowse.html#gac60ef4f9e006a920f1d72b6098743fbc\">api.h</a>\n</li>\n<li>sp_artistbrowse_tophit_track()\n: <a class=\"el\" href=\"group__artistbrowse.html#ga5da55f43def03fe9f0d2c8b252b9755a\">api.h</a>\n</li>\n<li>sp_artistbrowse_track()\n: <a class=\"el\" href=\"group__artistbrowse.html#ga45d28771a856f935dc40ab40e27dec4c\">api.h</a>\n</li>\n<li>sp_artistbrowse_type\n: <a class=\"el\" href=\"group__session.html#gac86504cc9e8cadbc30c8aa8dbf355034\">api.h</a>\n</li>\n<li>sp_audio_buffer_stats\n: <a class=\"el\" href=\"group__session.html#ga25462859a596a247ba5cc1853fc32cca\">api.h</a>\n</li>\n<li>sp_audioformat\n: <a class=\"el\" href=\"group__session.html#ga5338d4a10576ba8d6ab11b70892d503c\">api.h</a>\n</li>\n<li>sp_availability\n: <a class=\"el\" href=\"group__session.html#gad7d9465769597b2a379ac704099adfdf\">api.h</a>\n</li>\n<li>sp_bitrate\n: <a class=\"el\" href=\"group__session.html#ga77ddd919314a7bb16140569af7a38fe2\">api.h</a>\n</li>\n<li>SP_BITRATE_160k\n: <a class=\"el\" href=\"group__session.html#gga77ddd919314a7bb16140569af7a38fe2a5b5c794224972f833a4b7eec9d7909c9\">api.h</a>\n</li>\n<li>SP_BITRATE_320k\n: <a class=\"el\" href=\"group__session.html#gga77ddd919314a7bb16140569af7a38fe2a9383c0dc9faefd2cbb38c3b9342c47e0\">api.h</a>\n</li>\n<li>SP_BITRATE_96k\n: <a class=\"el\" href=\"group__session.html#gga77ddd919314a7bb16140569af7a38fe2ad815a35af7e6bb5e2ef29418af62759b\">api.h</a>\n</li>\n<li>sp_build_id()\n: <a class=\"el\" href=\"api_8h.html#a181d0940997cb8b69869449cd826cf88\">api.h</a>\n</li>\n<li>SP_CONNECTION_RULE_ALLOW_SYNC_OVER_MOBILE\n: <a class=\"el\" href=\"group__session.html#ggad275d696685b2ad9ff1a2c3e16af6502a91a946573c44de44d74e9d20dbce4c74\">api.h</a>\n</li>\n<li>SP_CONNECTION_RULE_ALLOW_SYNC_OVER_WIFI\n: <a class=\"el\" href=\"group__session.html#ggad275d696685b2ad9ff1a2c3e16af6502a548f3734832ec65a992e598d8b91633d\">api.h</a>\n</li>\n<li>SP_CONNECTION_RULE_NETWORK\n: <a class=\"el\" href=\"group__session.html#ggad275d696685b2ad9ff1a2c3e16af6502aa39a1c21c17c55cd1547bc900ae2d386\">api.h</a>\n</li>\n<li>SP_CONNECTION_RULE_NETWORK_IF_ROAMING\n: <a class=\"el\" href=\"group__session.html#ggad275d696685b2ad9ff1a2c3e16af6502af2772ba84ee7e410ad99708a11955670\">api.h</a>\n</li>\n<li>sp_connection_rules\n: <a class=\"el\" href=\"group__session.html#gad275d696685b2ad9ff1a2c3e16af6502\">api.h</a>\n</li>\n<li>SP_CONNECTION_STATE_DISCONNECTED\n: <a class=\"el\" href=\"group__session.html#ggabf77bb5a124d5a6ee9a12c86abbc0d34ad1a6eb721675af4613f823c091538a8c\">api.h</a>\n</li>\n<li>SP_CONNECTION_STATE_LOGGED_IN\n: <a class=\"el\" href=\"group__session.html#ggabf77bb5a124d5a6ee9a12c86abbc0d34a88ae17b4168184e62e4c190c289c47c5\">api.h</a>\n</li>\n<li>SP_CONNECTION_STATE_LOGGED_OUT\n: <a class=\"el\" href=\"group__session.html#ggabf77bb5a124d5a6ee9a12c86abbc0d34ae31e9958a98211ecff5ecbcf7041dfa5\">api.h</a>\n</li>\n<li>SP_CONNECTION_STATE_OFFLINE\n: <a class=\"el\" href=\"group__session.html#ggabf77bb5a124d5a6ee9a12c86abbc0d34a63099ef9185ba287fcd2e77be3c47d8f\">api.h</a>\n</li>\n<li>SP_CONNECTION_STATE_UNDEFINED\n: <a class=\"el\" href=\"group__session.html#ggabf77bb5a124d5a6ee9a12c86abbc0d34a4ddf57518007eef86b06f496d7059484\">api.h</a>\n</li>\n<li>sp_connection_type\n: <a class=\"el\" href=\"group__session.html#ga3e8773baeb94189b9a1ff27d6a5e3553\">api.h</a>\n</li>\n<li>SP_CONNECTION_TYPE_MOBILE\n: <a class=\"el\" href=\"group__session.html#gga3e8773baeb94189b9a1ff27d6a5e3553a3ca3e6a85ac9d497914c35620ad5179d\">api.h</a>\n</li>\n<li>SP_CONNECTION_TYPE_MOBILE_ROAMING\n: <a class=\"el\" href=\"group__session.html#gga3e8773baeb94189b9a1ff27d6a5e3553a05b41bbfd369f9030a7daafc9395116e\">api.h</a>\n</li>\n<li>SP_CONNECTION_TYPE_NONE\n: <a class=\"el\" href=\"group__session.html#gga3e8773baeb94189b9a1ff27d6a5e3553aa7aae7ae3f7c471ece1c6aa2705d046c\">api.h</a>\n</li>\n<li>SP_CONNECTION_TYPE_UNKNOWN\n: <a class=\"el\" href=\"group__session.html#gga3e8773baeb94189b9a1ff27d6a5e3553af949fae9bc12f47b99ef290fa9b5d8a7\">api.h</a>\n</li>\n<li>SP_CONNECTION_TYPE_WIFI\n: <a class=\"el\" href=\"group__session.html#gga3e8773baeb94189b9a1ff27d6a5e3553a31d2cad7379f1bc2eeedd24c40541cb9\">api.h</a>\n</li>\n<li>SP_CONNECTION_TYPE_WIRED\n: <a class=\"el\" href=\"group__session.html#gga3e8773baeb94189b9a1ff27d6a5e3553a4f9f0c09e59af4114bb369ebcc474710\">api.h</a>\n</li>\n<li>sp_connectionstate\n: <a class=\"el\" href=\"group__session.html#gabf77bb5a124d5a6ee9a12c86abbc0d34\">api.h</a>\n</li>\n<li>sp_error\n: <a class=\"el\" href=\"group__error.html#gafd27986ce4cd9eeaeca8adda83c9eb6b\">api.h</a>\n</li>\n<li>SP_ERROR_API_INITIALIZATION_FAILED\n: <a class=\"el\" href=\"group__error.html#ggafd27986ce4cd9eeaeca8adda83c9eb6bac8c438bd52975d14edf23d040e93d114\">api.h</a>\n</li>\n<li>SP_ERROR_APPLICATION_BANNED\n: <a class=\"el\" href=\"group__error.html#ggafd27986ce4cd9eeaeca8adda83c9eb6ba46c3b6173bb5b09445164402ac5ed81f\">api.h</a>\n</li>\n<li>SP_ERROR_BAD_API_VERSION\n: <a class=\"el\" href=\"group__error.html#ggafd27986ce4cd9eeaeca8adda83c9eb6ba17c588fa9648e3649185e595bdb88d6f\">api.h</a>\n</li>\n<li>SP_ERROR_BAD_APPLICATION_KEY\n: <a class=\"el\" href=\"group__error.html#ggafd27986ce4cd9eeaeca8adda83c9eb6ba2bad808a467ee4418adaa40f4844d059\">api.h</a>\n</li>\n<li>SP_ERROR_BAD_USER_AGENT\n: <a class=\"el\" href=\"group__error.html#ggafd27986ce4cd9eeaeca8adda83c9eb6baf3597d4af35adb4fc0d0793ea26f77b4\">api.h</a>\n</li>\n<li>SP_ERROR_BAD_USERNAME_OR_PASSWORD\n: <a class=\"el\" href=\"group__error.html#ggafd27986ce4cd9eeaeca8adda83c9eb6ba41052a4a158fa18bb1b8bfdd8c37f7dc\">api.h</a>\n</li>\n<li>SP_ERROR_CANT_OPEN_TRACE_FILE\n: <a class=\"el\" href=\"group__error.html#ggafd27986ce4cd9eeaeca8adda83c9eb6badb3af1736912156cbe0b1e39eaeee1c8\">api.h</a>\n</li>\n<li>SP_ERROR_CLIENT_TOO_OLD\n: <a class=\"el\" href=\"group__error.html#ggafd27986ce4cd9eeaeca8adda83c9eb6ba995344026c012b3f59dc73e12c28b1ba\">api.h</a>\n</li>\n<li>SP_ERROR_INBOX_IS_FULL\n: <a class=\"el\" href=\"group__error.html#ggafd27986ce4cd9eeaeca8adda83c9eb6baa4bdf4298c9653549464d21ee528c881\">api.h</a>\n</li>\n<li>SP_ERROR_INDEX_OUT_OF_RANGE\n: <a class=\"el\" href=\"group__error.html#ggafd27986ce4cd9eeaeca8adda83c9eb6ba44b3f132578cbf9a43b5c048efcf63a2\">api.h</a>\n</li>\n<li>SP_ERROR_INVALID_ARGUMENT\n: <a class=\"el\" href=\"group__error.html#ggafd27986ce4cd9eeaeca8adda83c9eb6ba7f8be4d478e51d2b205157c7c538a3e5\">api.h</a>\n</li>\n<li>SP_ERROR_INVALID_DEVICE_ID\n: <a class=\"el\" href=\"group__error.html#ggafd27986ce4cd9eeaeca8adda83c9eb6ba846d94ada9e8db0c2bd5153f5801afa2\">api.h</a>\n</li>\n<li>SP_ERROR_INVALID_INDATA\n: <a class=\"el\" href=\"group__error.html#ggafd27986ce4cd9eeaeca8adda83c9eb6bac9f65a7270391d35342ca9e6c01d519d\">api.h</a>\n</li>\n<li>SP_ERROR_IS_LOADING\n: <a class=\"el\" href=\"group__error.html#ggafd27986ce4cd9eeaeca8adda83c9eb6ba17f54c30d01baedc24547e62ed417cdd\">api.h</a>\n</li>\n<li>SP_ERROR_LASTFM_AUTH_ERROR\n: <a class=\"el\" href=\"group__error.html#ggafd27986ce4cd9eeaeca8adda83c9eb6baf588c0f7a2d8d11acea28ac2a4de43c4\">api.h</a>\n</li>\n<li>sp_error_message()\n: <a class=\"el\" href=\"group__error.html#ga983dee341d3c2008830513b7cffe7bf3\">api.h</a>\n</li>\n<li>SP_ERROR_MISSING_CALLBACK\n: <a class=\"el\" href=\"group__error.html#ggafd27986ce4cd9eeaeca8adda83c9eb6babb1116e69e1d651f9f175dbc8bb5fa32\">api.h</a>\n</li>\n<li>SP_ERROR_NETWORK_DISABLED\n: <a class=\"el\" href=\"group__error.html#ggafd27986ce4cd9eeaeca8adda83c9eb6ba8fda4dd3ee6ac931337a871fbee02978\">api.h</a>\n</li>\n<li>SP_ERROR_NO_CACHE\n: <a class=\"el\" href=\"group__error.html#ggafd27986ce4cd9eeaeca8adda83c9eb6ba3b8851ee3ba2bd7ad1fe377d94ac38c0\">api.h</a>\n</li>\n<li>SP_ERROR_NO_CREDENTIALS\n: <a class=\"el\" href=\"group__error.html#ggafd27986ce4cd9eeaeca8adda83c9eb6ba9ad34b997313d790f142f24e77e78e2d\">api.h</a>\n</li>\n<li>SP_ERROR_NO_STREAM_AVAILABLE\n: <a class=\"el\" href=\"group__error.html#ggafd27986ce4cd9eeaeca8adda83c9eb6ba71307cc7b8460042603f3f322d1096f4\">api.h</a>\n</li>\n<li>SP_ERROR_NO_SUCH_USER\n: <a class=\"el\" href=\"group__error.html#ggafd27986ce4cd9eeaeca8adda83c9eb6baf8ade144869c958de534ecec9f9a36a9\">api.h</a>\n</li>\n<li>SP_ERROR_OFFLINE_DISK_CACHE\n: <a class=\"el\" href=\"group__error.html#ggafd27986ce4cd9eeaeca8adda83c9eb6bae6b9d9b013f1243548e4fbcf961559ff\">api.h</a>\n</li>\n<li>SP_ERROR_OFFLINE_EXPIRED\n: <a class=\"el\" href=\"group__error.html#ggafd27986ce4cd9eeaeca8adda83c9eb6ba7e16a1962fd4de081d73dc4a4e32eb04\">api.h</a>\n</li>\n<li>SP_ERROR_OFFLINE_LICENSE_ERROR\n: <a class=\"el\" href=\"group__error.html#ggafd27986ce4cd9eeaeca8adda83c9eb6ba9149b343017c0dea431839c8b4d9198c\">api.h</a>\n</li>\n<li>SP_ERROR_OFFLINE_LICENSE_LOST\n: <a class=\"el\" href=\"group__error.html#ggafd27986ce4cd9eeaeca8adda83c9eb6ba2c87afb46df21783f172a06b2c25d8f9\">api.h</a>\n</li>\n<li>SP_ERROR_OFFLINE_NOT_ALLOWED\n: <a class=\"el\" href=\"group__error.html#ggafd27986ce4cd9eeaeca8adda83c9eb6bae102b46f4fae3b7b6b34e21ea80d656f\">api.h</a>\n</li>\n<li>SP_ERROR_OFFLINE_TOO_MANY_TRACKS\n: <a class=\"el\" href=\"group__error.html#ggafd27986ce4cd9eeaeca8adda83c9eb6ba32fd1f63fd4dc7ec50bd11791f02953f\">api.h</a>\n</li>\n<li>SP_ERROR_OK\n: <a class=\"el\" href=\"group__error.html#ggafd27986ce4cd9eeaeca8adda83c9eb6ba16cb277dc84328e4b2c0cf6d5a0c0b8d\">api.h</a>\n</li>\n<li>SP_ERROR_OTHER_PERMANENT\n: <a class=\"el\" href=\"group__error.html#ggafd27986ce4cd9eeaeca8adda83c9eb6ba3f68775a5c001bd1de26afdf5ea4e09d\">api.h</a>\n</li>\n<li>SP_ERROR_OTHER_TRANSIENT\n: <a class=\"el\" href=\"group__error.html#ggafd27986ce4cd9eeaeca8adda83c9eb6baf139c18351a543862bd9393ccebc5f91\">api.h</a>\n</li>\n<li>SP_ERROR_PERMISSION_DENIED\n: <a class=\"el\" href=\"group__error.html#ggafd27986ce4cd9eeaeca8adda83c9eb6baaddac1f3b82e905711ab9ffe5b4b0329\">api.h</a>\n</li>\n<li>SP_ERROR_SYSTEM_FAILURE\n: <a class=\"el\" href=\"group__error.html#ggafd27986ce4cd9eeaeca8adda83c9eb6ba73d533e0f25f4ba4cecd6d2e2502b80b\">api.h</a>\n</li>\n<li>SP_ERROR_TRACK_NOT_PLAYABLE\n: <a class=\"el\" href=\"group__error.html#ggafd27986ce4cd9eeaeca8adda83c9eb6ba7b94fe2b53f58d91d4c3cda7bb706ff3\">api.h</a>\n</li>\n<li>SP_ERROR_UNABLE_TO_CONTACT_SERVER\n: <a class=\"el\" href=\"group__error.html#ggafd27986ce4cd9eeaeca8adda83c9eb6ba9d11d66176b6ae95bf00486e9e39866b\">api.h</a>\n</li>\n<li>SP_ERROR_USER_BANNED\n: <a class=\"el\" href=\"group__error.html#ggafd27986ce4cd9eeaeca8adda83c9eb6ba822f4031a82ab428cd04f2ecdc0e757f\">api.h</a>\n</li>\n<li>SP_ERROR_USER_NEEDS_PREMIUM\n: <a class=\"el\" href=\"group__error.html#ggafd27986ce4cd9eeaeca8adda83c9eb6ba96c08adfcda17005c63142cd4e4cd9bb\">api.h</a>\n</li>\n<li>sp_image\n: <a class=\"el\" href=\"group__types.html#ga61155ca7b1ba941e15490e417441917b\">api.h</a>\n</li>\n<li>sp_image_add_load_callback()\n: <a class=\"el\" href=\"group__image.html#gaa414f26ad1b9095645a83361597c92ce\">api.h</a>\n</li>\n<li>sp_image_add_ref()\n: <a class=\"el\" href=\"group__image.html#ga98c93dbedfb182243742131a5224b83b\">api.h</a>\n</li>\n<li>sp_image_create()\n: <a class=\"el\" href=\"group__image.html#gaf29e89f45945db2b3667bf9db4279c33\">api.h</a>\n</li>\n<li>sp_image_create_from_link()\n: <a class=\"el\" href=\"group__image.html#ga70fb25cd2b0caaf15f637f36e75524b9\">api.h</a>\n</li>\n<li>sp_image_data()\n: <a class=\"el\" href=\"group__image.html#ga03700a7dfa90bfc8200b89f15acd91aa\">api.h</a>\n</li>\n<li>sp_image_error()\n: <a class=\"el\" href=\"group__image.html#gae40103df87426b346e0d0413d8d3b0ff\">api.h</a>\n</li>\n<li>sp_image_format()\n: <a class=\"el\" href=\"group__image.html#ga04448e81ca4916ba7ed223d0d817e803\">api.h</a>\n</li>\n<li>SP_IMAGE_FORMAT_JPEG\n: <a class=\"el\" href=\"group__image.html#gga2cda19baf2460da5e81fb1917f54626ba6263674800bea702c4d913d4b07c135d\">api.h</a>\n</li>\n<li>SP_IMAGE_FORMAT_UNKNOWN\n: <a class=\"el\" href=\"group__image.html#gga2cda19baf2460da5e81fb1917f54626ba2fec8a1b400bd6cd5396b9852e4279b6\">api.h</a>\n</li>\n<li>sp_image_image_id()\n: <a class=\"el\" href=\"group__image.html#ga0ee0b98cc25c995fe208a992cc87d145\">api.h</a>\n</li>\n<li>sp_image_is_loaded()\n: <a class=\"el\" href=\"group__image.html#ga45312b1b9b5e5565485d61a8f0300e18\">api.h</a>\n</li>\n<li>sp_image_release()\n: <a class=\"el\" href=\"group__image.html#ga3df9af5f68b18df5a598b7510e9b587f\">api.h</a>\n</li>\n<li>sp_image_remove_load_callback()\n: <a class=\"el\" href=\"group__image.html#gaaee68c65d9eab3499f2b6be5d048d6ba\">api.h</a>\n</li>\n<li>sp_image_size\n: <a class=\"el\" href=\"group__session.html#ga61bc424465d776af3ceeb69eee2bb492\">api.h</a>\n</li>\n<li>SP_IMAGE_SIZE_LARGE\n: <a class=\"el\" href=\"group__session.html#gga61bc424465d776af3ceeb69eee2bb492a0a0b624afbb2a66ee3d7954202b89721\">api.h</a>\n</li>\n<li>SP_IMAGE_SIZE_NORMAL\n: <a class=\"el\" href=\"group__session.html#gga61bc424465d776af3ceeb69eee2bb492ad20c808fd1f8180d1f49f643975d1dd7\">api.h</a>\n</li>\n<li>SP_IMAGE_SIZE_SMALL\n: <a class=\"el\" href=\"group__session.html#gga61bc424465d776af3ceeb69eee2bb492ab9340b1bcf2129c3ad1328ea617d547f\">api.h</a>\n</li>\n<li>sp_imageformat\n: <a class=\"el\" href=\"group__image.html#ga2cda19baf2460da5e81fb1917f54626b\">api.h</a>\n</li>\n<li>sp_inbox\n: <a class=\"el\" href=\"group__types.html#gaec0f2e5098cebc05ce56adfc9b346510\">api.h</a>\n</li>\n<li>sp_inbox_add_ref()\n: <a class=\"el\" href=\"group__inbox.html#gadb6b607bc26b9d362de4da09ec1c864f\">api.h</a>\n</li>\n<li>sp_inbox_error()\n: <a class=\"el\" href=\"group__inbox.html#gaa452e9fe1fa7c9e2c780d28ce2ed63c5\">api.h</a>\n</li>\n<li>sp_inbox_post_tracks()\n: <a class=\"el\" href=\"group__inbox.html#gaee29e747ca10b36597d91689ae074aa2\">api.h</a>\n</li>\n<li>sp_inbox_release()\n: <a class=\"el\" href=\"group__inbox.html#ga73659a65af92d30e4ac1cf3e06e74a0a\">api.h</a>\n</li>\n<li>sp_link\n: <a class=\"el\" href=\"group__types.html#gaf90a23d6b662c96d52ac19f7f4bc1e39\">api.h</a>\n</li>\n<li>sp_link_add_ref()\n: <a class=\"el\" href=\"group__link.html#gac5a808b15bceed41508bd3863c8f4b3b\">api.h</a>\n</li>\n<li>sp_link_as_album()\n: <a class=\"el\" href=\"group__link.html#gaafa98628d0abadcca27dd3b227c7337b\">api.h</a>\n</li>\n<li>sp_link_as_artist()\n: <a class=\"el\" href=\"group__link.html#gab32979d26dcf68936202fa7aed7b6e49\">api.h</a>\n</li>\n<li>sp_link_as_string()\n: <a class=\"el\" href=\"group__link.html#ga9f169be53f098adcf12f7a10b8bd3ef7\">api.h</a>\n</li>\n<li>sp_link_as_track()\n: <a class=\"el\" href=\"group__link.html#ga2560687997d7ce0fbf4f05251d87d32a\">api.h</a>\n</li>\n<li>sp_link_as_track_and_offset()\n: <a class=\"el\" href=\"group__link.html#ga80f6f752832f76c268c0bfd3ca45e6d2\">api.h</a>\n</li>\n<li>sp_link_as_user()\n: <a class=\"el\" href=\"group__link.html#ga3e29975f47fc0a51be813b4774a3d6f3\">api.h</a>\n</li>\n<li>sp_link_create_from_album()\n: <a class=\"el\" href=\"group__link.html#ga040627b0df84425947c82cd8890122ad\">api.h</a>\n</li>\n<li>sp_link_create_from_album_cover()\n: <a class=\"el\" href=\"group__link.html#gaa87e346c29f1077d7a62c364719d4a55\">api.h</a>\n</li>\n<li>sp_link_create_from_artist()\n: <a class=\"el\" href=\"group__link.html#ga3196ce9de3da4f1d5944a0b58bd80540\">api.h</a>\n</li>\n<li>sp_link_create_from_artist_portrait()\n: <a class=\"el\" href=\"group__link.html#gaafb25ee14bfb27f9cbbab1b039d4d225\">api.h</a>\n</li>\n<li>sp_link_create_from_artistbrowse_portrait()\n: <a class=\"el\" href=\"group__link.html#ga32218fbd912ddddbb749cb42a72b6bcd\">api.h</a>\n</li>\n<li>sp_link_create_from_image()\n: <a class=\"el\" href=\"group__link.html#gaa85fbea312127db44685b7e9dc492042\">api.h</a>\n</li>\n<li>sp_link_create_from_playlist()\n: <a class=\"el\" href=\"group__link.html#ga805392bfa8e526eebedc1cf5a7bcae0f\">api.h</a>\n</li>\n<li>sp_link_create_from_search()\n: <a class=\"el\" href=\"group__link.html#ga95c97ba4de9c4040047276ad618a108e\">api.h</a>\n</li>\n<li>sp_link_create_from_string()\n: <a class=\"el\" href=\"group__link.html#gaea9c39f35f7986fc9fed4584fa211127\">api.h</a>\n</li>\n<li>sp_link_create_from_track()\n: <a class=\"el\" href=\"group__link.html#ga82c29419ce70e2b504670e3d45167d5d\">api.h</a>\n</li>\n<li>sp_link_create_from_user()\n: <a class=\"el\" href=\"group__link.html#gaaa78b1750179c17f8152408cea43efef\">api.h</a>\n</li>\n<li>sp_link_release()\n: <a class=\"el\" href=\"group__link.html#ga2b06ab16d1f6436cd8d36dbff2b5c022\">api.h</a>\n</li>\n<li>sp_link_type()\n: <a class=\"el\" href=\"group__link.html#ga6140f924c696d53469bb8930cd53e1e6\">api.h</a>\n</li>\n<li>sp_linktype\n: <a class=\"el\" href=\"group__link.html#gabe9611f04086cdbed6e4e6e1fd913b98\">api.h</a>\n</li>\n<li>SP_LINKTYPE_ALBUM\n: <a class=\"el\" href=\"group__link.html#ggabe9611f04086cdbed6e4e6e1fd913b98a7716eb95eed852d08300e6e64febc7f3\">api.h</a>\n</li>\n<li>SP_LINKTYPE_ARTIST\n: <a class=\"el\" href=\"group__link.html#ggabe9611f04086cdbed6e4e6e1fd913b98a4402b3b001aebb39fd55296f83c60b7e\">api.h</a>\n</li>\n<li>SP_LINKTYPE_IMAGE\n: <a class=\"el\" href=\"group__link.html#ggabe9611f04086cdbed6e4e6e1fd913b98a1b20b8e2b8773df47b241dc7d28ea0e8\">api.h</a>\n</li>\n<li>SP_LINKTYPE_INVALID\n: <a class=\"el\" href=\"group__link.html#ggabe9611f04086cdbed6e4e6e1fd913b98a88b0098486cde586b4dcffb623ac6e63\">api.h</a>\n</li>\n<li>SP_LINKTYPE_LOCALTRACK\n: <a class=\"el\" href=\"group__link.html#ggabe9611f04086cdbed6e4e6e1fd913b98a0698cd0123190c7af55daf79bb642805\">api.h</a>\n</li>\n<li>SP_LINKTYPE_PLAYLIST\n: <a class=\"el\" href=\"group__link.html#ggabe9611f04086cdbed6e4e6e1fd913b98a2640ed065a64b6a9f67e71bbeb2af2dd\">api.h</a>\n</li>\n<li>SP_LINKTYPE_PROFILE\n: <a class=\"el\" href=\"group__link.html#ggabe9611f04086cdbed6e4e6e1fd913b98ab7a356adce8b1ea34daf21532c7b50e6\">api.h</a>\n</li>\n<li>SP_LINKTYPE_SEARCH\n: <a class=\"el\" href=\"group__link.html#ggabe9611f04086cdbed6e4e6e1fd913b98ad5909ab9b1cca702163e116b04b6ee8e\">api.h</a>\n</li>\n<li>SP_LINKTYPE_STARRED\n: <a class=\"el\" href=\"group__link.html#ggabe9611f04086cdbed6e4e6e1fd913b98ab649bd86d0fc55ab3fafed3050261353\">api.h</a>\n</li>\n<li>SP_LINKTYPE_TRACK\n: <a class=\"el\" href=\"group__link.html#ggabe9611f04086cdbed6e4e6e1fd913b98a5911dbb7258ed160b2f9c114cef152f1\">api.h</a>\n</li>\n<li>sp_localtrack_create()\n: <a class=\"el\" href=\"group__track.html#ga0fb814ef23636fdecda64e3a63b15a23\">api.h</a>\n</li>\n<li>sp_offline_num_playlists()\n: <a class=\"el\" href=\"group__session.html#gad6cee58fa44453b7a4fd2ae2266df055\">api.h</a>\n</li>\n<li>sp_offline_sync_get_status()\n: <a class=\"el\" href=\"group__session.html#ga02525cd659a34728047cd3801049e822\">api.h</a>\n</li>\n<li>sp_offline_sync_status\n: <a class=\"el\" href=\"group__session.html#gaa7f24f13d6d105869c405045a4cc2a20\">api.h</a>\n</li>\n<li>sp_offline_time_left()\n: <a class=\"el\" href=\"group__session.html#gac36816dc42825db9a5a2fbd2694f20af\">api.h</a>\n</li>\n<li>sp_offline_tracks_to_sync()\n: <a class=\"el\" href=\"group__session.html#gaf535124b4208c279cb98a061834e6411\">api.h</a>\n</li>\n<li>sp_playlist\n: <a class=\"el\" href=\"group__types.html#ga1bcf54cbc117a20ab2c15e59eb3a8174\">api.h</a>\n</li>\n<li>sp_playlist_add_callbacks()\n: <a class=\"el\" href=\"group__playlist.html#gab15fca12d387c69b4998a4d2b48e5b32\">api.h</a>\n</li>\n<li>sp_playlist_add_ref()\n: <a class=\"el\" href=\"group__playlist.html#gacb10979add5a954e5c1600ef9c5b17a8\">api.h</a>\n</li>\n<li>sp_playlist_add_tracks()\n: <a class=\"el\" href=\"group__playlist.html#ga2344a47133f7f0aed0a67e154ecc4dc4\">api.h</a>\n</li>\n<li>sp_playlist_callbacks\n: <a class=\"el\" href=\"group__playlist.html#ga8249fe3d53c6dce0f154d0bfd3e80c6a\">api.h</a>\n</li>\n<li>sp_playlist_create()\n: <a class=\"el\" href=\"group__playlist.html#ga342a6a0cfe10531ef7cb3c6629c1e8e7\">api.h</a>\n</li>\n<li>sp_playlist_get_description()\n: <a class=\"el\" href=\"group__playlist.html#gab1d8e0ee9b436ecbb104bbd6cc0665be\">api.h</a>\n</li>\n<li>sp_playlist_get_image()\n: <a class=\"el\" href=\"group__playlist.html#ga409cb6b2a88db7242ec939b6644e8c30\">api.h</a>\n</li>\n<li>sp_playlist_get_offline_download_completed()\n: <a class=\"el\" href=\"group__playlist.html#ga83ca1a25f50834f8e6f8ee1e883a8c6e\">api.h</a>\n</li>\n<li>sp_playlist_get_offline_status()\n: <a class=\"el\" href=\"group__playlist.html#ga7170157af21445c37a21a2241f91ff06\">api.h</a>\n</li>\n<li>sp_playlist_has_pending_changes()\n: <a class=\"el\" href=\"group__playlist.html#gaf0e39b5969259d10625eb398af0f3f43\">api.h</a>\n</li>\n<li>sp_playlist_is_collaborative()\n: <a class=\"el\" href=\"group__playlist.html#ga8ad160f654f02f13690568070dd57353\">api.h</a>\n</li>\n<li>sp_playlist_is_in_ram()\n: <a class=\"el\" href=\"group__playlist.html#ga28456d1242693c6d890516dc782ab3ec\">api.h</a>\n</li>\n<li>sp_playlist_is_loaded()\n: <a class=\"el\" href=\"group__playlist.html#gaee8ea6c07dfdca3397e27b278fa4870a\">api.h</a>\n</li>\n<li>sp_playlist_name()\n: <a class=\"el\" href=\"group__playlist.html#ga61b7e33cc1aedb4e31a2af75ae0ac8cc\">api.h</a>\n</li>\n<li>sp_playlist_num_subscribers()\n: <a class=\"el\" href=\"group__playlist.html#ga967ad87f0db702513ecda82546f667c5\">api.h</a>\n</li>\n<li>sp_playlist_num_tracks()\n: <a class=\"el\" href=\"group__playlist.html#ga684a3acc60f99b3b26488ed813ee5d23\">api.h</a>\n</li>\n<li>sp_playlist_offline_status\n: <a class=\"el\" href=\"group__session.html#ga811fa52ed0fdb5cda732682e27e40417\">api.h</a>\n</li>\n<li>SP_PLAYLIST_OFFLINE_STATUS_DOWNLOADING\n: <a class=\"el\" href=\"group__session.html#gga811fa52ed0fdb5cda732682e27e40417abc999c70761d392b26753708e9a2cfa1\">api.h</a>\n</li>\n<li>SP_PLAYLIST_OFFLINE_STATUS_NO\n: <a class=\"el\" href=\"group__session.html#gga811fa52ed0fdb5cda732682e27e40417abef62e4e3a4af8827fed7fe3aa733ca0\">api.h</a>\n</li>\n<li>SP_PLAYLIST_OFFLINE_STATUS_WAITING\n: <a class=\"el\" href=\"group__session.html#gga811fa52ed0fdb5cda732682e27e40417a7d929bbf4f1df3633b283e39b9c95919\">api.h</a>\n</li>\n<li>SP_PLAYLIST_OFFLINE_STATUS_YES\n: <a class=\"el\" href=\"group__session.html#gga811fa52ed0fdb5cda732682e27e40417affed38ac820e084b96fb48e3d1939584\">api.h</a>\n</li>\n<li>sp_playlist_owner()\n: <a class=\"el\" href=\"group__playlist.html#gac3e4295d3353eb9998402aedfdbd55de\">api.h</a>\n</li>\n<li>sp_playlist_release()\n: <a class=\"el\" href=\"group__playlist.html#gacb9250eb530869b039541a8b62dfab6c\">api.h</a>\n</li>\n<li>sp_playlist_remove_callbacks()\n: <a class=\"el\" href=\"group__playlist.html#ga7fcbf909a0fa8bf25f0b1d1e7dd0e160\">api.h</a>\n</li>\n<li>sp_playlist_remove_tracks()\n: <a class=\"el\" href=\"group__playlist.html#gabd62cd7ff9484b4c31ff7f159ec41b6a\">api.h</a>\n</li>\n<li>sp_playlist_rename()\n: <a class=\"el\" href=\"group__playlist.html#gad6c3880c514353e204fdd90830b516ec\">api.h</a>\n</li>\n<li>sp_playlist_reorder_tracks()\n: <a class=\"el\" href=\"group__playlist.html#ga90ffd8c9fc6abc7375e89f4cb49adb11\">api.h</a>\n</li>\n<li>sp_playlist_set_autolink_tracks()\n: <a class=\"el\" href=\"group__playlist.html#ga0bde47f340e0cd590a78007c6af69307\">api.h</a>\n</li>\n<li>sp_playlist_set_collaborative()\n: <a class=\"el\" href=\"group__playlist.html#gad15410bcc2ebd986adabda865830bce4\">api.h</a>\n</li>\n<li>sp_playlist_set_in_ram()\n: <a class=\"el\" href=\"group__playlist.html#gaf6ca8a349bdd982f6c8dda52ed691017\">api.h</a>\n</li>\n<li>sp_playlist_set_offline_mode()\n: <a class=\"el\" href=\"group__playlist.html#ga784f648f9cc431ef3b51f3491c2f169f\">api.h</a>\n</li>\n<li>sp_playlist_subscribers()\n: <a class=\"el\" href=\"group__playlist.html#gad49f491babc475f8d4aeea1b4452ff8b\">api.h</a>\n</li>\n<li>sp_playlist_subscribers_free()\n: <a class=\"el\" href=\"group__playlist.html#gae7754b74b1c3c8f5222ca43b6608ce6a\">api.h</a>\n</li>\n<li>sp_playlist_track()\n: <a class=\"el\" href=\"group__playlist.html#ga7a03854fe6072476306780d23c6cac16\">api.h</a>\n</li>\n<li>sp_playlist_track_create_time()\n: <a class=\"el\" href=\"group__playlist.html#gab8e77f8d63e787f8aa1a066d74daa74c\">api.h</a>\n</li>\n<li>sp_playlist_track_creator()\n: <a class=\"el\" href=\"group__playlist.html#ga80fcd9e7b40c791433c07d66e2ad432a\">api.h</a>\n</li>\n<li>sp_playlist_track_message()\n: <a class=\"el\" href=\"group__playlist.html#ga6887b9dabb30a060b10bdb75f8b3f971\">api.h</a>\n</li>\n<li>sp_playlist_track_seen()\n: <a class=\"el\" href=\"group__playlist.html#gab9e00ee5bc6b5dc0b3d58cbdb32c0c7b\">api.h</a>\n</li>\n<li>sp_playlist_track_set_seen()\n: <a class=\"el\" href=\"group__playlist.html#ga69f5cc1bdd7dbdcdb476a7b1d2b7834d\">api.h</a>\n</li>\n<li>sp_playlist_type\n: <a class=\"el\" href=\"group__session.html#ga86723f553db2db6a8f507cd748948ad4\">api.h</a>\n</li>\n<li>SP_PLAYLIST_TYPE_END_FOLDER\n: <a class=\"el\" href=\"group__session.html#ggafdd7117213605e6f2671c4f289b44609a3ec52ad1d99d8e32e1b9de31e3f5187a\">api.h</a>\n</li>\n<li>SP_PLAYLIST_TYPE_PLACEHOLDER\n: <a class=\"el\" href=\"group__session.html#ggafdd7117213605e6f2671c4f289b44609ad4f860ef76154e3e2c0d9da2f57a2784\">api.h</a>\n</li>\n<li>SP_PLAYLIST_TYPE_PLAYLIST\n: <a class=\"el\" href=\"group__session.html#ggafdd7117213605e6f2671c4f289b44609a6bd6bf9b62018fa9bbf969835c2f3077\">api.h</a>\n</li>\n<li>SP_PLAYLIST_TYPE_START_FOLDER\n: <a class=\"el\" href=\"group__session.html#ggafdd7117213605e6f2671c4f289b44609a4d3266991787f9438deb9de83d9200da\">api.h</a>\n</li>\n<li>sp_playlist_update_subscribers()\n: <a class=\"el\" href=\"group__playlist.html#ga9ebbf147230b3ca98b68e556cf24e6bd\">api.h</a>\n</li>\n<li>sp_playlistcontainer\n: <a class=\"el\" href=\"group__types.html#ga45a2febbe167483e48dab8d606d462d7\">api.h</a>\n</li>\n<li>sp_playlistcontainer_add_callbacks()\n: <a class=\"el\" href=\"group__playlist.html#ga1976cb49c391cdd2dbe7c40d1bc71570\">api.h</a>\n</li>\n<li>sp_playlistcontainer_add_folder()\n: <a class=\"el\" href=\"group__playlist.html#ga0862502eea52fc5f2465ebad6fd98796\">api.h</a>\n</li>\n<li>sp_playlistcontainer_add_new_playlist()\n: <a class=\"el\" href=\"group__playlist.html#ga840b82b1074a7ca1c9eacd351bed24c2\">api.h</a>\n</li>\n<li>sp_playlistcontainer_add_playlist()\n: <a class=\"el\" href=\"group__playlist.html#ga87699479087915b741ceef4eebe69ad8\">api.h</a>\n</li>\n<li>sp_playlistcontainer_add_ref()\n: <a class=\"el\" href=\"group__playlist.html#ga2138c537a6ebcd35a01eea54d0dd1e8f\">api.h</a>\n</li>\n<li>sp_playlistcontainer_callbacks\n: <a class=\"el\" href=\"group__playlist.html#ga8786e3840bb3774fc929183e3a9df281\">api.h</a>\n</li>\n<li>sp_playlistcontainer_clear_unseen_tracks()\n: <a class=\"el\" href=\"group__playlist.html#gadaad604c35e543363e1dd5b23c462db0\">api.h</a>\n</li>\n<li>sp_playlistcontainer_get_unseen_tracks()\n: <a class=\"el\" href=\"group__playlist.html#gad9e11b45843ee4a147b43038a2e55f13\">api.h</a>\n</li>\n<li>sp_playlistcontainer_is_loaded()\n: <a class=\"el\" href=\"group__playlist.html#gae23cb67b4b26bca663034997c4418fa8\">api.h</a>\n</li>\n<li>sp_playlistcontainer_move_playlist()\n: <a class=\"el\" href=\"group__playlist.html#gad9be708159957d4c1e5ef905550808c5\">api.h</a>\n</li>\n<li>sp_playlistcontainer_num_playlists()\n: <a class=\"el\" href=\"group__playlist.html#ga7a1cbf558b2b364b8249d4ce432df700\">api.h</a>\n</li>\n<li>sp_playlistcontainer_owner()\n: <a class=\"el\" href=\"group__playlist.html#gad4fc67d1386dd637f778f4e735a36894\">api.h</a>\n</li>\n<li>sp_playlistcontainer_playlist()\n: <a class=\"el\" href=\"group__playlist.html#ga5ddd8c8064c281a14c6fd7877f522dc6\">api.h</a>\n</li>\n<li>sp_playlistcontainer_playlist_folder_id()\n: <a class=\"el\" href=\"group__playlist.html#ga6939f9db71199612fc5a19d395e3a7f8\">api.h</a>\n</li>\n<li>sp_playlistcontainer_playlist_folder_name()\n: <a class=\"el\" href=\"group__playlist.html#ga852e5f5bcd4520be2e3d6d5d94def44a\">api.h</a>\n</li>\n<li>sp_playlistcontainer_playlist_type()\n: <a class=\"el\" href=\"group__playlist.html#ga79286860a3eeada495e97c5ad1fd7ebf\">api.h</a>\n</li>\n<li>sp_playlistcontainer_release()\n: <a class=\"el\" href=\"group__playlist.html#ga0311c7c3c4f26028e5edd4aacb36dbf8\">api.h</a>\n</li>\n<li>sp_playlistcontainer_remove_callbacks()\n: <a class=\"el\" href=\"group__playlist.html#gafb5242b8f0f9964cec29d32f4d6c1164\">api.h</a>\n</li>\n<li>sp_playlistcontainer_remove_playlist()\n: <a class=\"el\" href=\"group__playlist.html#ga1ae1d51c4305940ae5c5c98c12be0afc\">api.h</a>\n</li>\n<li>sp_relation_type\n: <a class=\"el\" href=\"group__user.html#ga6af84143c0622b6fc5539bb1ae111e5b\">api.h</a>\n</li>\n<li>SP_RELATION_TYPE_BIDIRECTIONAL\n: <a class=\"el\" href=\"group__user.html#gga6af84143c0622b6fc5539bb1ae111e5ba4bfef63cabd016cf1e6b11347a05d389\">api.h</a>\n</li>\n<li>SP_RELATION_TYPE_NONE\n: <a class=\"el\" href=\"group__user.html#gga6af84143c0622b6fc5539bb1ae111e5bad9805f100828a9d3b64c3cc66f2ac5c1\">api.h</a>\n</li>\n<li>SP_RELATION_TYPE_UNIDIRECTIONAL\n: <a class=\"el\" href=\"group__user.html#gga6af84143c0622b6fc5539bb1ae111e5ba06b2f38745c467e7e362c7744cb74205\">api.h</a>\n</li>\n<li>SP_RELATION_TYPE_UNKNOWN\n: <a class=\"el\" href=\"group__user.html#gga6af84143c0622b6fc5539bb1ae111e5ba18f24164eef0e687b351c2aa6753e35e\">api.h</a>\n</li>\n<li>sp_sampletype\n: <a class=\"el\" href=\"group__session.html#ga5ef462e78d5a5af60dd0e7085b1ba512\">api.h</a>\n</li>\n<li>SP_SAMPLETYPE_INT16_NATIVE_ENDIAN\n: <a class=\"el\" href=\"group__session.html#gga087d21080010768316cfb55d938eb94daa829b269d191cca95ecb02c2bc59da42\">api.h</a>\n</li>\n<li>sp_search\n: <a class=\"el\" href=\"group__types.html#gac95893a6b23d4b19f6f149eed6ead1fd\">api.h</a>\n</li>\n<li>sp_search_add_ref()\n: <a class=\"el\" href=\"group__search.html#ga92e45a5edb1e33e64fdb857bd8eb9ad5\">api.h</a>\n</li>\n<li>sp_search_album()\n: <a class=\"el\" href=\"group__search.html#ga4ba7723e70db0c6a4569c4bcd44f0e98\">api.h</a>\n</li>\n<li>sp_search_artist()\n: <a class=\"el\" href=\"group__search.html#ga79b3d532d5a20a3b2bf2a087eead7888\">api.h</a>\n</li>\n<li>sp_search_create()\n: <a class=\"el\" href=\"group__search.html#ga2f64dfbcc1313e7d5179998cb28208d4\">api.h</a>\n</li>\n<li>sp_search_did_you_mean()\n: <a class=\"el\" href=\"group__search.html#ga8561c1da8b93ecdc8f2d325a9d19199b\">api.h</a>\n</li>\n<li>sp_search_error()\n: <a class=\"el\" href=\"group__search.html#ga7cf655e37a823f952d30270d4fb60f10\">api.h</a>\n</li>\n<li>sp_search_is_loaded()\n: <a class=\"el\" href=\"group__search.html#ga70e8c404d8c7ce0bbef70c2b274417cd\">api.h</a>\n</li>\n<li>sp_search_num_albums()\n: <a class=\"el\" href=\"group__search.html#ga0c456a6396c4c05fbc8677ea641ef1f7\">api.h</a>\n</li>\n<li>sp_search_num_artists()\n: <a class=\"el\" href=\"group__search.html#gabd375a613c2dadecad8c13f8aca6f2d3\">api.h</a>\n</li>\n<li>sp_search_num_playlists()\n: <a class=\"el\" href=\"group__search.html#gaa9f007f439d8241bf632f9abb8d926c9\">api.h</a>\n</li>\n<li>sp_search_num_tracks()\n: <a class=\"el\" href=\"group__search.html#ga1dd18cf7b3b3b7f4bf6e92a2140378d0\">api.h</a>\n</li>\n<li>sp_search_playlist()\n: <a class=\"el\" href=\"group__search.html#ga4175fba17f355b1c0bd361357181ea35\">api.h</a>\n</li>\n<li>sp_search_playlist_image_uri()\n: <a class=\"el\" href=\"group__search.html#gac4463fab4ea25e0a5d5079c959a1781c\">api.h</a>\n</li>\n<li>sp_search_playlist_name()\n: <a class=\"el\" href=\"group__search.html#ga933cd5d5a0ccca9906082ca4549a4ed7\">api.h</a>\n</li>\n<li>sp_search_playlist_uri()\n: <a class=\"el\" href=\"group__search.html#ga0071a3d30f0f0c4e477bf923e9014ff5\">api.h</a>\n</li>\n<li>sp_search_query()\n: <a class=\"el\" href=\"group__search.html#ga127e9c2bf98e3602ecfc2926b9d242bf\">api.h</a>\n</li>\n<li>sp_search_release()\n: <a class=\"el\" href=\"group__search.html#ga4e01d43067d9f8c533c985f90143821b\">api.h</a>\n</li>\n<li>sp_search_total_albums()\n: <a class=\"el\" href=\"group__search.html#gaafd3b228adbc028937383d0d45730581\">api.h</a>\n</li>\n<li>sp_search_total_artists()\n: <a class=\"el\" href=\"group__search.html#ga305a4118625e0f70cfb14161a0112fd5\">api.h</a>\n</li>\n<li>sp_search_total_playlists()\n: <a class=\"el\" href=\"group__search.html#ga2e286415a6ba8dbf85ea677906f2798c\">api.h</a>\n</li>\n<li>sp_search_total_tracks()\n: <a class=\"el\" href=\"group__search.html#gab4e50582c517b4639fd1afd6fb011587\">api.h</a>\n</li>\n<li>sp_search_track()\n: <a class=\"el\" href=\"group__search.html#gae9da7ca59ce0bbd73f7bcef4e15c4da8\">api.h</a>\n</li>\n<li>sp_search_type\n: <a class=\"el\" href=\"group__session.html#ga99e8e9176ce40fff08a9be8b944edb09\">api.h</a>\n</li>\n<li>sp_session\n: <a class=\"el\" href=\"group__types.html#ga70dd19c6f824cf6a159575aa4c128b53\">api.h</a>\n</li>\n<li>sp_session_callbacks\n: <a class=\"el\" href=\"group__session.html#gaf1d92302cd5d0d4a032e1408188c8fd5\">api.h</a>\n</li>\n<li>sp_session_config\n: <a class=\"el\" href=\"group__session.html#ga372b25a93da38d4d707b0c2eaa7b3ebb\">api.h</a>\n</li>\n<li>sp_session_connectionstate()\n: <a class=\"el\" href=\"group__session.html#ga34a7c9527705ab7d23b742006d81ea35\">api.h</a>\n</li>\n<li>sp_session_create()\n: <a class=\"el\" href=\"group__session.html#gaf2891f2daced4ff6da84219d6376b3aa\">api.h</a>\n</li>\n<li>sp_session_flush_caches()\n: <a class=\"el\" href=\"group__session.html#ga34005bb06ee3de8ee4221597a0335cca\">api.h</a>\n</li>\n<li>sp_session_forget_me()\n: <a class=\"el\" href=\"group__session.html#ga61e6b796d9e07682c018e888b901a191\">api.h</a>\n</li>\n<li>sp_session_get_volume_normalization()\n: <a class=\"el\" href=\"group__session.html#ga7913df06394360f255c77fb87af0f1fe\">api.h</a>\n</li>\n<li>sp_session_inbox_create()\n: <a class=\"el\" href=\"group__session.html#gac72ccb51031c846101134b73195bb9ec\">api.h</a>\n</li>\n<li>sp_session_is_private_session()\n: <a class=\"el\" href=\"group__session.html#ga72702ee06bc96c074804388d24344149\">api.h</a>\n</li>\n<li>sp_session_is_scrobbling()\n: <a class=\"el\" href=\"group__session.html#ga6a56bc82ff0b369bb6e0f035534ce33d\">api.h</a>\n</li>\n<li>sp_session_is_scrobbling_possible()\n: <a class=\"el\" href=\"group__session.html#ga0fad03ceabcf8d68af78f0f35fcbcc8d\">api.h</a>\n</li>\n<li>sp_session_login()\n: <a class=\"el\" href=\"group__session.html#ga4533a992a120cacb109c892a852afe2a\">api.h</a>\n</li>\n<li>sp_session_logout()\n: <a class=\"el\" href=\"group__session.html#gab7f08ca0939985b30ae2d1ed9db1d726\">api.h</a>\n</li>\n<li>sp_session_player_load()\n: <a class=\"el\" href=\"group__session.html#gac73bf2c569a43d824439b557d5e4b293\">api.h</a>\n</li>\n<li>sp_session_player_play()\n: <a class=\"el\" href=\"group__session.html#gab66c5915967e4f90db945b118e620624\">api.h</a>\n</li>\n<li>sp_session_player_prefetch()\n: <a class=\"el\" href=\"group__session.html#gaf42e30a1f430ac7c436c7d9f0485368d\">api.h</a>\n</li>\n<li>sp_session_player_seek()\n: <a class=\"el\" href=\"group__session.html#ga3430cd4f11541868d3f83eaa31aecf44\">api.h</a>\n</li>\n<li>sp_session_player_unload()\n: <a class=\"el\" href=\"group__session.html#gafa7ee2803f119451bb8be3bf28746975\">api.h</a>\n</li>\n<li>sp_session_playlistcontainer()\n: <a class=\"el\" href=\"group__session.html#ga319767f0b795f1c46a08390b587c5671\">api.h</a>\n</li>\n<li>sp_session_preferred_bitrate()\n: <a class=\"el\" href=\"group__session.html#gacd590e095b011af42fb10046117846fe\">api.h</a>\n</li>\n<li>sp_session_preferred_offline_bitrate()\n: <a class=\"el\" href=\"group__session.html#ga4bba5f828d6c87692f2c355cc8f07c61\">api.h</a>\n</li>\n<li>sp_session_process_events()\n: <a class=\"el\" href=\"group__session.html#gaff27cb730db6debf55e750e39e7fadd7\">api.h</a>\n</li>\n<li>sp_session_publishedcontainer_for_user_create()\n: <a class=\"el\" href=\"group__session.html#ga4ad3a1de596a41f275120dad3bb4685d\">api.h</a>\n</li>\n<li>sp_session_release()\n: <a class=\"el\" href=\"group__session.html#gab81c540b76f7425a9cc0dbf270c09674\">api.h</a>\n</li>\n<li>sp_session_relogin()\n: <a class=\"el\" href=\"group__session.html#gae1bc9bebd230226c3d48925cd1be6edf\">api.h</a>\n</li>\n<li>sp_session_remembered_user()\n: <a class=\"el\" href=\"group__session.html#gab349c7bfe59e10e167bd75c20df9fc97\">api.h</a>\n</li>\n<li>sp_session_set_cache_size()\n: <a class=\"el\" href=\"group__session.html#ga6f27c55d1ce9f3f794fcce7bee7adfea\">api.h</a>\n</li>\n<li>sp_session_set_connection_rules()\n: <a class=\"el\" href=\"group__session.html#ga0ac85299c37710321b6d64713e1d6ba8\">api.h</a>\n</li>\n<li>sp_session_set_connection_type()\n: <a class=\"el\" href=\"group__session.html#gaf81c61799e0ccdbba048fb79ec050930\">api.h</a>\n</li>\n<li>sp_session_set_private_session()\n: <a class=\"el\" href=\"group__session.html#ga42a8f0999316ac7f141926092879ad2f\">api.h</a>\n</li>\n<li>sp_session_set_scrobbling()\n: <a class=\"el\" href=\"group__session.html#ga2475a1fbc2eeacccb96b7f36efd36725\">api.h</a>\n</li>\n<li>sp_session_set_social_credentials()\n: <a class=\"el\" href=\"group__session.html#ga9e5ee46ef5e75aa462607caac984f2de\">api.h</a>\n</li>\n<li>sp_session_set_volume_normalization()\n: <a class=\"el\" href=\"group__session.html#ga4e14f58356d00e3693be84623bf6bd11\">api.h</a>\n</li>\n<li>sp_session_starred_create()\n: <a class=\"el\" href=\"group__session.html#ga02391c9e28cff0a602f7139542e0238f\">api.h</a>\n</li>\n<li>sp_session_starred_for_user_create()\n: <a class=\"el\" href=\"group__session.html#ga9be806a719a6399bfe1fd0d4c125e0eb\">api.h</a>\n</li>\n<li>sp_session_user()\n: <a class=\"el\" href=\"group__session.html#ga267bbcae24b6bb1fd56de56678a5f455\">api.h</a>\n</li>\n<li>sp_session_user_country()\n: <a class=\"el\" href=\"group__session.html#ga54c7693afa9be664f3ea870feb0df8d9\">api.h</a>\n</li>\n<li>sp_session_user_name()\n: <a class=\"el\" href=\"group__session.html#gac7a365c2166738909cdb901edebc3f70\">api.h</a>\n</li>\n<li>sp_session_userdata()\n: <a class=\"el\" href=\"group__session.html#gabfb3f59b20ae0b225e154eb9095152b2\">api.h</a>\n</li>\n<li>sp_subscribers\n: <a class=\"el\" href=\"group__session.html#gafb515e30d134c61b8eaaff3177af0b5b\">api.h</a>\n</li>\n<li>SP_TOPLIST_REGION\n: <a class=\"el\" href=\"group__toplist.html#gaa078b44491f976af43e4941fd1dd032c\">api.h</a>\n</li>\n<li>SP_TOPLIST_REGION_EVERYWHERE\n: <a class=\"el\" href=\"group__toplist.html#gga6fa5cfed2cbb33f2f64542d0b63f6c8da9e9136541401041c7d5c37708b7a927f\">api.h</a>\n</li>\n<li>SP_TOPLIST_REGION_USER\n: <a class=\"el\" href=\"group__toplist.html#gga6fa5cfed2cbb33f2f64542d0b63f6c8da6912eff58c71f5c74b78f48af5305375\">api.h</a>\n</li>\n<li>SP_TOPLIST_TYPE_ALBUMS\n: <a class=\"el\" href=\"group__toplist.html#gga220f32522efb2828e4f8ffb949af234aae8002818ef10eb2c75ec2058ce11cf6b\">api.h</a>\n</li>\n<li>SP_TOPLIST_TYPE_ARTISTS\n: <a class=\"el\" href=\"group__toplist.html#gga220f32522efb2828e4f8ffb949af234aa41523e58badf9e3901beea3f53e5d28e\">api.h</a>\n</li>\n<li>SP_TOPLIST_TYPE_TRACKS\n: <a class=\"el\" href=\"group__toplist.html#gga220f32522efb2828e4f8ffb949af234aa6a85f8384ec77cb9cb5746966b0f0e28\">api.h</a>\n</li>\n<li>sp_toplistbrowse\n: <a class=\"el\" href=\"group__types.html#ga723de429cd073bcf5d13fb4e0f466ffd\">api.h</a>\n</li>\n<li>sp_toplistbrowse_add_ref()\n: <a class=\"el\" href=\"group__toplist.html#ga421a19f128e5f3ae4b36e63a133a2a83\">api.h</a>\n</li>\n<li>sp_toplistbrowse_album()\n: <a class=\"el\" href=\"group__toplist.html#gaa080ace445d269f56942ac3d7f1f157e\">api.h</a>\n</li>\n<li>sp_toplistbrowse_artist()\n: <a class=\"el\" href=\"group__toplist.html#ga504cc45074d40c817dffbcc2906ef57f\">api.h</a>\n</li>\n<li>sp_toplistbrowse_backend_request_duration()\n: <a class=\"el\" href=\"group__toplist.html#gab9cf87d6b6a8cbd8d36cd6e94a3270ee\">api.h</a>\n</li>\n<li>sp_toplistbrowse_create()\n: <a class=\"el\" href=\"group__toplist.html#gac2fe366e0050747438e09cdd22ed0e31\">api.h</a>\n</li>\n<li>sp_toplistbrowse_error()\n: <a class=\"el\" href=\"group__toplist.html#ga9b881929e74d97f64814ae54953ce4d7\">api.h</a>\n</li>\n<li>sp_toplistbrowse_is_loaded()\n: <a class=\"el\" href=\"group__toplist.html#gaff81156c09d311c4f6a82d28a32d7968\">api.h</a>\n</li>\n<li>sp_toplistbrowse_num_albums()\n: <a class=\"el\" href=\"group__toplist.html#ga69f5e70269c1eb08e1ddb1c77bb8c3e3\">api.h</a>\n</li>\n<li>sp_toplistbrowse_num_artists()\n: <a class=\"el\" href=\"group__toplist.html#gae2f5c09fbbf947834b1b1e73461f1fb3\">api.h</a>\n</li>\n<li>sp_toplistbrowse_num_tracks()\n: <a class=\"el\" href=\"group__toplist.html#gaeb0ddfd565474dc7e444aabebbc119b7\">api.h</a>\n</li>\n<li>sp_toplistbrowse_release()\n: <a class=\"el\" href=\"group__toplist.html#gac6cf969c9cb6b431aeaa4723820ca8de\">api.h</a>\n</li>\n<li>sp_toplistbrowse_track()\n: <a class=\"el\" href=\"group__toplist.html#gaf3d00b8bf089134a4f320a8d3d6ab683\">api.h</a>\n</li>\n<li>sp_toplistregion\n: <a class=\"el\" href=\"group__toplist.html#ga6fa5cfed2cbb33f2f64542d0b63f6c8d\">api.h</a>\n</li>\n<li>sp_toplisttype\n: <a class=\"el\" href=\"group__toplist.html#ga220f32522efb2828e4f8ffb949af234a\">api.h</a>\n</li>\n<li>sp_track\n: <a class=\"el\" href=\"group__types.html#ga47bbd2262f0c8b5d7147af7d62198e48\">api.h</a>\n</li>\n<li>sp_track_add_ref()\n: <a class=\"el\" href=\"group__track.html#ga7d86041a2bf75590f55978521c08e38c\">api.h</a>\n</li>\n<li>sp_track_album()\n: <a class=\"el\" href=\"group__track.html#ga39a0f52244472cb2d450ea9ba6807304\">api.h</a>\n</li>\n<li>sp_track_artist()\n: <a class=\"el\" href=\"group__track.html#ga67cd0c035627a1e4a54642213fdf1d75\">api.h</a>\n</li>\n<li>sp_track_availability\n: <a class=\"el\" href=\"group__session.html#ga60c7ff53ddbc04c036a23181b7275d69\">api.h</a>\n</li>\n<li>SP_TRACK_AVAILABILITY_AVAILABLE\n: <a class=\"el\" href=\"group__session.html#ggad7d9465769597b2a379ac704099adfdfa3b837ba6d740b5650b0113734a3b2ff7\">api.h</a>\n</li>\n<li>SP_TRACK_AVAILABILITY_BANNED_BY_ARTIST\n: <a class=\"el\" href=\"group__session.html#ggad7d9465769597b2a379ac704099adfdfaeb5d63e89c543f513cd3054969e50914\">api.h</a>\n</li>\n<li>SP_TRACK_AVAILABILITY_NOT_STREAMABLE\n: <a class=\"el\" href=\"group__session.html#ggad7d9465769597b2a379ac704099adfdfae7b2cfafa10288ecc50df97621bbe940\">api.h</a>\n</li>\n<li>SP_TRACK_AVAILABILITY_UNAVAILABLE\n: <a class=\"el\" href=\"group__session.html#ggad7d9465769597b2a379ac704099adfdfa44bc1e6f138910b3f8dbd309325e0077\">api.h</a>\n</li>\n<li>sp_track_disc()\n: <a class=\"el\" href=\"group__track.html#ga9d464ee4a5c8836b59888952b960223a\">api.h</a>\n</li>\n<li>sp_track_duration()\n: <a class=\"el\" href=\"group__track.html#gac817937bd8d8355b6a1949b76d0b5560\">api.h</a>\n</li>\n<li>sp_track_error()\n: <a class=\"el\" href=\"group__track.html#ga947c0f7755b0c4955ca0b0993db0f2b5\">api.h</a>\n</li>\n<li>sp_track_get_availability()\n: <a class=\"el\" href=\"group__track.html#ga9c78846badae6567fe9f9a3792fd06c8\">api.h</a>\n</li>\n<li>sp_track_get_playable()\n: <a class=\"el\" href=\"group__track.html#ga112dca47d0bac39818b55119ef134ffd\">api.h</a>\n</li>\n<li>sp_track_index()\n: <a class=\"el\" href=\"group__track.html#ga25c1df9d32fd58f243397740b29c3f61\">api.h</a>\n</li>\n<li>sp_track_is_autolinked()\n: <a class=\"el\" href=\"group__track.html#ga4eeb86de13187697cd9dfe0b0934988d\">api.h</a>\n</li>\n<li>sp_track_is_loaded()\n: <a class=\"el\" href=\"group__track.html#ga8b69cf193679c7e00031ae43e61c6a54\">api.h</a>\n</li>\n<li>sp_track_is_local()\n: <a class=\"el\" href=\"group__track.html#gabcb75da69e0338006bdbd2f2f467f082\">api.h</a>\n</li>\n<li>sp_track_is_placeholder()\n: <a class=\"el\" href=\"group__track.html#ga2367d906c578e674d0d470d8c1ee3b33\">api.h</a>\n</li>\n<li>sp_track_is_starred()\n: <a class=\"el\" href=\"group__track.html#gab17d380ac941e102af0f308ad885b3c3\">api.h</a>\n</li>\n<li>sp_track_name()\n: <a class=\"el\" href=\"group__track.html#ga8eb423d3cc2cbfb743c7f23ffb8d0fad\">api.h</a>\n</li>\n<li>sp_track_num_artists()\n: <a class=\"el\" href=\"group__track.html#ga0aa945fc43e35d36cc334a52735d83b2\">api.h</a>\n</li>\n<li>SP_TRACK_OFFLINE_DONE\n: <a class=\"el\" href=\"group__session.html#ggaeaa41aad3c0047409996a6ec3b03203fac54d46cbc73de7686a1ad8daf269532a\">api.h</a>\n</li>\n<li>SP_TRACK_OFFLINE_DONE_EXPIRED\n: <a class=\"el\" href=\"group__session.html#ggaeaa41aad3c0047409996a6ec3b03203fa00fe430030fb6a8a49a46c11cca7326c\">api.h</a>\n</li>\n<li>SP_TRACK_OFFLINE_DONE_RESYNC\n: <a class=\"el\" href=\"group__session.html#ggaeaa41aad3c0047409996a6ec3b03203fa5f3e19627de4509ae4a3864fd29edee6\">api.h</a>\n</li>\n<li>SP_TRACK_OFFLINE_DOWNLOADING\n: <a class=\"el\" href=\"group__session.html#ggaeaa41aad3c0047409996a6ec3b03203fa7dcf6dfc56a8421200451d07a476f370\">api.h</a>\n</li>\n<li>SP_TRACK_OFFLINE_ERROR\n: <a class=\"el\" href=\"group__session.html#ggaeaa41aad3c0047409996a6ec3b03203fa86618798c266540bdc889dd037a52631\">api.h</a>\n</li>\n<li>sp_track_offline_get_status()\n: <a class=\"el\" href=\"group__track.html#ga281e0ad4373579c5d24202ea1f93fe7b\">api.h</a>\n</li>\n<li>SP_TRACK_OFFLINE_LIMIT_EXCEEDED\n: <a class=\"el\" href=\"group__session.html#ggaeaa41aad3c0047409996a6ec3b03203fa405a9b7a3fa489ad2dadbb108794e247\">api.h</a>\n</li>\n<li>SP_TRACK_OFFLINE_NO\n: <a class=\"el\" href=\"group__session.html#ggaeaa41aad3c0047409996a6ec3b03203faad1a1cba82ce9f9be678f4d1042eddec\">api.h</a>\n</li>\n<li>sp_track_offline_status\n: <a class=\"el\" href=\"group__session.html#gaeaa41aad3c0047409996a6ec3b03203f\">api.h</a>\n</li>\n<li>SP_TRACK_OFFLINE_WAITING\n: <a class=\"el\" href=\"group__session.html#ggaeaa41aad3c0047409996a6ec3b03203fa1fdd2a518dcdc072cfca27a0ca4f2581\">api.h</a>\n</li>\n<li>sp_track_popularity()\n: <a class=\"el\" href=\"group__track.html#ga4570f08f968edbff519b44d2241d2255\">api.h</a>\n</li>\n<li>sp_track_release()\n: <a class=\"el\" href=\"group__track.html#gaa11098d82e6c2ae42fc2ea1486e741de\">api.h</a>\n</li>\n<li>sp_track_set_starred()\n: <a class=\"el\" href=\"group__track.html#ga34b5a712fb2c683402ff78df73e7545c\">api.h</a>\n</li>\n<li>sp_user\n: <a class=\"el\" href=\"group__types.html#gaed2dbaa1eebd6752f76613daad9158bc\">api.h</a>\n</li>\n<li>sp_user_add_ref()\n: <a class=\"el\" href=\"group__user.html#ga232816a3c8f42ef2663b8d99261f2dae\">api.h</a>\n</li>\n<li>sp_user_canonical_name()\n: <a class=\"el\" href=\"group__user.html#gad9ac5456cd129c31d2c577ba14e88f8c\">api.h</a>\n</li>\n<li>sp_user_display_name()\n: <a class=\"el\" href=\"group__user.html#ga0052befb81a93bb7106ca863de892610\">api.h</a>\n</li>\n<li>sp_user_is_loaded()\n: <a class=\"el\" href=\"group__user.html#ga0996fb9814564e4ad39b8a500cb3de21\">api.h</a>\n</li>\n<li>sp_user_release()\n: <a class=\"el\" href=\"group__user.html#gab1ffba4355073e1f72594c9e1b22ebb4\">api.h</a>\n</li>\n<li>SPOTIFY_API_VERSION\n: <a class=\"el\" href=\"group__session.html#ga63b2309874193750ec3395f6cae32899\">api.h</a>\n</li>\n</ul>\n</div>\n<hr size=\"1\"><address style=\"text-align: right;\"><small>\nGenerated on Wed Jun 13 2012 14:22:40.<br>\nCopyright &copy; 2006&ndash;2012 Spotify Ltd</small></address>\n</body>\n</html>\n"
  },
  {
    "path": "libspotify/docs/html/globals_0x74.html",
    "content": "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\n<html xmlns=\"http://www.w3.org/1999/xhtml\">\n<head>\n<meta http-equiv=\"Content-Type\" content=\"text/xhtml;charset=UTF-8\"/>\n<title>libspotify: Data Fields</title>\n<link href=\"tabs.css\" rel=\"stylesheet\" type=\"text/css\"/>\n<link href=\"doxygen.css\" rel=\"stylesheet\" type=\"text/css\"/>\n</head>\n<body>\n<!-- Generated by Doxygen 1.7.1 -->\n<div class=\"navigation\" id=\"top\">\n  <div class=\"tabs\">\n    <ul class=\"tablist\">\n      <li><a href=\"index.html\"><span>Main&nbsp;Page</span></a></li>\n      <li><a href=\"modules.html\"><span>Modules</span></a></li>\n      <li><a href=\"annotated.html\"><span>Data&nbsp;Structures</span></a></li>\n      <li class=\"current\"><a href=\"files.html\"><span>Files</span></a></li>\n      <li><a href=\"examples.html\"><span>Examples</span></a></li>\n    </ul>\n  </div>\n  <div class=\"tabs2\">\n    <ul class=\"tablist\">\n      <li><a href=\"files.html\"><span>File&nbsp;List</span></a></li>\n      <li class=\"current\"><a href=\"globals.html\"><span>Globals</span></a></li>\n    </ul>\n  </div>\n  <div class=\"tabs2\">\n    <ul class=\"tablist\">\n      <li class=\"current\"><a href=\"globals.html\"><span>All</span></a></li>\n      <li><a href=\"globals_func.html\"><span>Functions</span></a></li>\n      <li><a href=\"globals_type.html\"><span>Typedefs</span></a></li>\n      <li><a href=\"globals_enum.html\"><span>Enumerations</span></a></li>\n      <li><a href=\"globals_eval.html\"><span>Enumerator</span></a></li>\n      <li><a href=\"globals_defs.html\"><span>Defines</span></a></li>\n    </ul>\n  </div>\n  <div class=\"tabs3\">\n    <ul class=\"tablist\">\n      <li><a href=\"globals.html#index_a\"><span>a</span></a></li>\n      <li><a href=\"globals_0x69.html#index_i\"><span>i</span></a></li>\n      <li><a href=\"globals_0x73.html#index_s\"><span>s</span></a></li>\n      <li class=\"current\"><a href=\"globals_0x74.html#index_t\"><span>t</span></a></li>\n    </ul>\n  </div>\n</div>\n<div class=\"contents\">\nHere is a list of all documented functions, variables, defines, enums, and typedefs with links to the documentation:\n\n<h3><a class=\"anchor\" id=\"index_t\"></a>- t -</h3><ul>\n<li>toplistbrowse_complete_cb\n: <a class=\"el\" href=\"group__toplist.html#gafe8e94ae23133105f35c03b9e3836a0a\">api.h</a>\n</li>\n</ul>\n</div>\n<hr size=\"1\"><address style=\"text-align: right;\"><small>\nGenerated on Wed Jun 13 2012 14:22:40.<br>\nCopyright &copy; 2006&ndash;2012 Spotify Ltd</small></address>\n</body>\n</html>\n"
  },
  {
    "path": "libspotify/docs/html/globals_defs.html",
    "content": "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\n<html xmlns=\"http://www.w3.org/1999/xhtml\">\n<head>\n<meta http-equiv=\"Content-Type\" content=\"text/xhtml;charset=UTF-8\"/>\n<title>libspotify: Data Fields</title>\n<link href=\"tabs.css\" rel=\"stylesheet\" type=\"text/css\"/>\n<link href=\"doxygen.css\" rel=\"stylesheet\" type=\"text/css\"/>\n</head>\n<body>\n<!-- Generated by Doxygen 1.7.1 -->\n<div class=\"navigation\" id=\"top\">\n  <div class=\"tabs\">\n    <ul class=\"tablist\">\n      <li><a href=\"index.html\"><span>Main&nbsp;Page</span></a></li>\n      <li><a href=\"modules.html\"><span>Modules</span></a></li>\n      <li><a href=\"annotated.html\"><span>Data&nbsp;Structures</span></a></li>\n      <li class=\"current\"><a href=\"files.html\"><span>Files</span></a></li>\n      <li><a href=\"examples.html\"><span>Examples</span></a></li>\n    </ul>\n  </div>\n  <div class=\"tabs2\">\n    <ul class=\"tablist\">\n      <li><a href=\"files.html\"><span>File&nbsp;List</span></a></li>\n      <li class=\"current\"><a href=\"globals.html\"><span>Globals</span></a></li>\n    </ul>\n  </div>\n  <div class=\"tabs2\">\n    <ul class=\"tablist\">\n      <li><a href=\"globals.html\"><span>All</span></a></li>\n      <li><a href=\"globals_func.html\"><span>Functions</span></a></li>\n      <li><a href=\"globals_type.html\"><span>Typedefs</span></a></li>\n      <li><a href=\"globals_enum.html\"><span>Enumerations</span></a></li>\n      <li><a href=\"globals_eval.html\"><span>Enumerator</span></a></li>\n      <li class=\"current\"><a href=\"globals_defs.html\"><span>Defines</span></a></li>\n    </ul>\n  </div>\n</div>\n<div class=\"contents\">\n&nbsp;<ul>\n<li>SP_TOPLIST_REGION\n: <a class=\"el\" href=\"group__toplist.html#gaa078b44491f976af43e4941fd1dd032c\">api.h</a>\n</li>\n<li>SPOTIFY_API_VERSION\n: <a class=\"el\" href=\"group__session.html#ga63b2309874193750ec3395f6cae32899\">api.h</a>\n</li>\n</ul>\n</div>\n<hr size=\"1\"><address style=\"text-align: right;\"><small>\nGenerated on Wed Jun 13 2012 14:22:40.<br>\nCopyright &copy; 2006&ndash;2012 Spotify Ltd</small></address>\n</body>\n</html>\n"
  },
  {
    "path": "libspotify/docs/html/globals_enum.html",
    "content": "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\n<html xmlns=\"http://www.w3.org/1999/xhtml\">\n<head>\n<meta http-equiv=\"Content-Type\" content=\"text/xhtml;charset=UTF-8\"/>\n<title>libspotify: Data Fields</title>\n<link href=\"tabs.css\" rel=\"stylesheet\" type=\"text/css\"/>\n<link href=\"doxygen.css\" rel=\"stylesheet\" type=\"text/css\"/>\n</head>\n<body>\n<!-- Generated by Doxygen 1.7.1 -->\n<div class=\"navigation\" id=\"top\">\n  <div class=\"tabs\">\n    <ul class=\"tablist\">\n      <li><a href=\"index.html\"><span>Main&nbsp;Page</span></a></li>\n      <li><a href=\"modules.html\"><span>Modules</span></a></li>\n      <li><a href=\"annotated.html\"><span>Data&nbsp;Structures</span></a></li>\n      <li class=\"current\"><a href=\"files.html\"><span>Files</span></a></li>\n      <li><a href=\"examples.html\"><span>Examples</span></a></li>\n    </ul>\n  </div>\n  <div class=\"tabs2\">\n    <ul class=\"tablist\">\n      <li><a href=\"files.html\"><span>File&nbsp;List</span></a></li>\n      <li class=\"current\"><a href=\"globals.html\"><span>Globals</span></a></li>\n    </ul>\n  </div>\n  <div class=\"tabs2\">\n    <ul class=\"tablist\">\n      <li><a href=\"globals.html\"><span>All</span></a></li>\n      <li><a href=\"globals_func.html\"><span>Functions</span></a></li>\n      <li><a href=\"globals_type.html\"><span>Typedefs</span></a></li>\n      <li class=\"current\"><a href=\"globals_enum.html\"><span>Enumerations</span></a></li>\n      <li><a href=\"globals_eval.html\"><span>Enumerator</span></a></li>\n      <li><a href=\"globals_defs.html\"><span>Defines</span></a></li>\n    </ul>\n  </div>\n</div>\n<div class=\"contents\">\n&nbsp;<ul>\n<li>sp_albumtype\n: <a class=\"el\" href=\"group__album.html#ga019b49a9d1633b61daa79c80ea01d5c3\">api.h</a>\n</li>\n<li>sp_artistbrowse_type\n: <a class=\"el\" href=\"group__session.html#gac86504cc9e8cadbc30c8aa8dbf355034\">api.h</a>\n</li>\n<li>sp_availability\n: <a class=\"el\" href=\"group__session.html#gad7d9465769597b2a379ac704099adfdf\">api.h</a>\n</li>\n<li>sp_bitrate\n: <a class=\"el\" href=\"group__session.html#ga77ddd919314a7bb16140569af7a38fe2\">api.h</a>\n</li>\n<li>sp_connection_rules\n: <a class=\"el\" href=\"group__session.html#gad275d696685b2ad9ff1a2c3e16af6502\">api.h</a>\n</li>\n<li>sp_connection_type\n: <a class=\"el\" href=\"group__session.html#ga3e8773baeb94189b9a1ff27d6a5e3553\">api.h</a>\n</li>\n<li>sp_connectionstate\n: <a class=\"el\" href=\"group__session.html#gabf77bb5a124d5a6ee9a12c86abbc0d34\">api.h</a>\n</li>\n<li>sp_error\n: <a class=\"el\" href=\"group__error.html#gafd27986ce4cd9eeaeca8adda83c9eb6b\">api.h</a>\n</li>\n<li>sp_image_size\n: <a class=\"el\" href=\"group__session.html#ga61bc424465d776af3ceeb69eee2bb492\">api.h</a>\n</li>\n<li>sp_imageformat\n: <a class=\"el\" href=\"group__image.html#ga2cda19baf2460da5e81fb1917f54626b\">api.h</a>\n</li>\n<li>sp_linktype\n: <a class=\"el\" href=\"group__link.html#gabe9611f04086cdbed6e4e6e1fd913b98\">api.h</a>\n</li>\n<li>sp_playlist_offline_status\n: <a class=\"el\" href=\"group__session.html#ga811fa52ed0fdb5cda732682e27e40417\">api.h</a>\n</li>\n<li>sp_playlist_type\n: <a class=\"el\" href=\"group__session.html#gafdd7117213605e6f2671c4f289b44609\">api.h</a>\n</li>\n<li>sp_relation_type\n: <a class=\"el\" href=\"group__user.html#ga6af84143c0622b6fc5539bb1ae111e5b\">api.h</a>\n</li>\n<li>sp_sampletype\n: <a class=\"el\" href=\"group__session.html#ga087d21080010768316cfb55d938eb94d\">api.h</a>\n</li>\n<li>sp_search_type\n: <a class=\"el\" href=\"group__session.html#ga99e8e9176ce40fff08a9be8b944edb09\">api.h</a>\n</li>\n<li>sp_toplistregion\n: <a class=\"el\" href=\"group__toplist.html#ga6fa5cfed2cbb33f2f64542d0b63f6c8d\">api.h</a>\n</li>\n<li>sp_toplisttype\n: <a class=\"el\" href=\"group__toplist.html#ga220f32522efb2828e4f8ffb949af234a\">api.h</a>\n</li>\n<li>sp_track_offline_status\n: <a class=\"el\" href=\"group__session.html#gaeaa41aad3c0047409996a6ec3b03203f\">api.h</a>\n</li>\n</ul>\n</div>\n<hr size=\"1\"><address style=\"text-align: right;\"><small>\nGenerated on Wed Jun 13 2012 14:22:40.<br>\nCopyright &copy; 2006&ndash;2012 Spotify Ltd</small></address>\n</body>\n</html>\n"
  },
  {
    "path": "libspotify/docs/html/globals_eval.html",
    "content": "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\n<html xmlns=\"http://www.w3.org/1999/xhtml\">\n<head>\n<meta http-equiv=\"Content-Type\" content=\"text/xhtml;charset=UTF-8\"/>\n<title>libspotify: Data Fields</title>\n<link href=\"tabs.css\" rel=\"stylesheet\" type=\"text/css\"/>\n<link href=\"doxygen.css\" rel=\"stylesheet\" type=\"text/css\"/>\n</head>\n<body>\n<!-- Generated by Doxygen 1.7.1 -->\n<div class=\"navigation\" id=\"top\">\n  <div class=\"tabs\">\n    <ul class=\"tablist\">\n      <li><a href=\"index.html\"><span>Main&nbsp;Page</span></a></li>\n      <li><a href=\"modules.html\"><span>Modules</span></a></li>\n      <li><a href=\"annotated.html\"><span>Data&nbsp;Structures</span></a></li>\n      <li class=\"current\"><a href=\"files.html\"><span>Files</span></a></li>\n      <li><a href=\"examples.html\"><span>Examples</span></a></li>\n    </ul>\n  </div>\n  <div class=\"tabs2\">\n    <ul class=\"tablist\">\n      <li><a href=\"files.html\"><span>File&nbsp;List</span></a></li>\n      <li class=\"current\"><a href=\"globals.html\"><span>Globals</span></a></li>\n    </ul>\n  </div>\n  <div class=\"tabs2\">\n    <ul class=\"tablist\">\n      <li><a href=\"globals.html\"><span>All</span></a></li>\n      <li><a href=\"globals_func.html\"><span>Functions</span></a></li>\n      <li><a href=\"globals_type.html\"><span>Typedefs</span></a></li>\n      <li><a href=\"globals_enum.html\"><span>Enumerations</span></a></li>\n      <li class=\"current\"><a href=\"globals_eval.html\"><span>Enumerator</span></a></li>\n      <li><a href=\"globals_defs.html\"><span>Defines</span></a></li>\n    </ul>\n  </div>\n  <div class=\"tabs3\">\n    <ul class=\"tablist\">\n      <li><a href=\"#index_s\"><span>s</span></a></li>\n    </ul>\n  </div>\n</div>\n<div class=\"contents\">\n&nbsp;\n\n<h3><a class=\"anchor\" id=\"index_s\"></a>- s -</h3><ul>\n<li>SP_ALBUMTYPE_ALBUM\n: <a class=\"el\" href=\"group__album.html#gga019b49a9d1633b61daa79c80ea01d5c3ad1693d93a2c05c053fc4fd77886af8dd\">api.h</a>\n</li>\n<li>SP_ALBUMTYPE_COMPILATION\n: <a class=\"el\" href=\"group__album.html#gga019b49a9d1633b61daa79c80ea01d5c3a8fee6ba46e8876037f4f2e46c6d6c6af\">api.h</a>\n</li>\n<li>SP_ALBUMTYPE_SINGLE\n: <a class=\"el\" href=\"group__album.html#gga019b49a9d1633b61daa79c80ea01d5c3a3b6f78b733f1bc18a5e4fa18c020fc73\">api.h</a>\n</li>\n<li>SP_ALBUMTYPE_UNKNOWN\n: <a class=\"el\" href=\"group__album.html#gga019b49a9d1633b61daa79c80ea01d5c3ad564ed5f1f0659929fe5ec700513873f\">api.h</a>\n</li>\n<li>SP_ARTISTBROWSE_FULL\n: <a class=\"el\" href=\"group__session.html#ggac86504cc9e8cadbc30c8aa8dbf355034a2914168528aded818177c013a0dd7e87\">api.h</a>\n</li>\n<li>SP_ARTISTBROWSE_NO_ALBUMS\n: <a class=\"el\" href=\"group__session.html#ggac86504cc9e8cadbc30c8aa8dbf355034ac0032981f8dbf44c022e6a7ab1672167\">api.h</a>\n</li>\n<li>SP_ARTISTBROWSE_NO_TRACKS\n: <a class=\"el\" href=\"group__session.html#ggac86504cc9e8cadbc30c8aa8dbf355034afbad1e58606b3230dce5bc3320c95d12\">api.h</a>\n</li>\n<li>SP_BITRATE_160k\n: <a class=\"el\" href=\"group__session.html#gga77ddd919314a7bb16140569af7a38fe2a5b5c794224972f833a4b7eec9d7909c9\">api.h</a>\n</li>\n<li>SP_BITRATE_320k\n: <a class=\"el\" href=\"group__session.html#gga77ddd919314a7bb16140569af7a38fe2a9383c0dc9faefd2cbb38c3b9342c47e0\">api.h</a>\n</li>\n<li>SP_BITRATE_96k\n: <a class=\"el\" href=\"group__session.html#gga77ddd919314a7bb16140569af7a38fe2ad815a35af7e6bb5e2ef29418af62759b\">api.h</a>\n</li>\n<li>SP_CONNECTION_RULE_ALLOW_SYNC_OVER_MOBILE\n: <a class=\"el\" href=\"group__session.html#ggad275d696685b2ad9ff1a2c3e16af6502a91a946573c44de44d74e9d20dbce4c74\">api.h</a>\n</li>\n<li>SP_CONNECTION_RULE_ALLOW_SYNC_OVER_WIFI\n: <a class=\"el\" href=\"group__session.html#ggad275d696685b2ad9ff1a2c3e16af6502a548f3734832ec65a992e598d8b91633d\">api.h</a>\n</li>\n<li>SP_CONNECTION_RULE_NETWORK\n: <a class=\"el\" href=\"group__session.html#ggad275d696685b2ad9ff1a2c3e16af6502aa39a1c21c17c55cd1547bc900ae2d386\">api.h</a>\n</li>\n<li>SP_CONNECTION_RULE_NETWORK_IF_ROAMING\n: <a class=\"el\" href=\"group__session.html#ggad275d696685b2ad9ff1a2c3e16af6502af2772ba84ee7e410ad99708a11955670\">api.h</a>\n</li>\n<li>SP_CONNECTION_STATE_DISCONNECTED\n: <a class=\"el\" href=\"group__session.html#ggabf77bb5a124d5a6ee9a12c86abbc0d34ad1a6eb721675af4613f823c091538a8c\">api.h</a>\n</li>\n<li>SP_CONNECTION_STATE_LOGGED_IN\n: <a class=\"el\" href=\"group__session.html#ggabf77bb5a124d5a6ee9a12c86abbc0d34a88ae17b4168184e62e4c190c289c47c5\">api.h</a>\n</li>\n<li>SP_CONNECTION_STATE_LOGGED_OUT\n: <a class=\"el\" href=\"group__session.html#ggabf77bb5a124d5a6ee9a12c86abbc0d34ae31e9958a98211ecff5ecbcf7041dfa5\">api.h</a>\n</li>\n<li>SP_CONNECTION_STATE_OFFLINE\n: <a class=\"el\" href=\"group__session.html#ggabf77bb5a124d5a6ee9a12c86abbc0d34a63099ef9185ba287fcd2e77be3c47d8f\">api.h</a>\n</li>\n<li>SP_CONNECTION_STATE_UNDEFINED\n: <a class=\"el\" href=\"group__session.html#ggabf77bb5a124d5a6ee9a12c86abbc0d34a4ddf57518007eef86b06f496d7059484\">api.h</a>\n</li>\n<li>SP_CONNECTION_TYPE_MOBILE\n: <a class=\"el\" href=\"group__session.html#gga3e8773baeb94189b9a1ff27d6a5e3553a3ca3e6a85ac9d497914c35620ad5179d\">api.h</a>\n</li>\n<li>SP_CONNECTION_TYPE_MOBILE_ROAMING\n: <a class=\"el\" href=\"group__session.html#gga3e8773baeb94189b9a1ff27d6a5e3553a05b41bbfd369f9030a7daafc9395116e\">api.h</a>\n</li>\n<li>SP_CONNECTION_TYPE_NONE\n: <a class=\"el\" href=\"group__session.html#gga3e8773baeb94189b9a1ff27d6a5e3553aa7aae7ae3f7c471ece1c6aa2705d046c\">api.h</a>\n</li>\n<li>SP_CONNECTION_TYPE_UNKNOWN\n: <a class=\"el\" href=\"group__session.html#gga3e8773baeb94189b9a1ff27d6a5e3553af949fae9bc12f47b99ef290fa9b5d8a7\">api.h</a>\n</li>\n<li>SP_CONNECTION_TYPE_WIFI\n: <a class=\"el\" href=\"group__session.html#gga3e8773baeb94189b9a1ff27d6a5e3553a31d2cad7379f1bc2eeedd24c40541cb9\">api.h</a>\n</li>\n<li>SP_CONNECTION_TYPE_WIRED\n: <a class=\"el\" href=\"group__session.html#gga3e8773baeb94189b9a1ff27d6a5e3553a4f9f0c09e59af4114bb369ebcc474710\">api.h</a>\n</li>\n<li>SP_ERROR_API_INITIALIZATION_FAILED\n: <a class=\"el\" href=\"group__error.html#ggafd27986ce4cd9eeaeca8adda83c9eb6bac8c438bd52975d14edf23d040e93d114\">api.h</a>\n</li>\n<li>SP_ERROR_APPLICATION_BANNED\n: <a class=\"el\" href=\"group__error.html#ggafd27986ce4cd9eeaeca8adda83c9eb6ba46c3b6173bb5b09445164402ac5ed81f\">api.h</a>\n</li>\n<li>SP_ERROR_BAD_API_VERSION\n: <a class=\"el\" href=\"group__error.html#ggafd27986ce4cd9eeaeca8adda83c9eb6ba17c588fa9648e3649185e595bdb88d6f\">api.h</a>\n</li>\n<li>SP_ERROR_BAD_APPLICATION_KEY\n: <a class=\"el\" href=\"group__error.html#ggafd27986ce4cd9eeaeca8adda83c9eb6ba2bad808a467ee4418adaa40f4844d059\">api.h</a>\n</li>\n<li>SP_ERROR_BAD_USER_AGENT\n: <a class=\"el\" href=\"group__error.html#ggafd27986ce4cd9eeaeca8adda83c9eb6baf3597d4af35adb4fc0d0793ea26f77b4\">api.h</a>\n</li>\n<li>SP_ERROR_BAD_USERNAME_OR_PASSWORD\n: <a class=\"el\" href=\"group__error.html#ggafd27986ce4cd9eeaeca8adda83c9eb6ba41052a4a158fa18bb1b8bfdd8c37f7dc\">api.h</a>\n</li>\n<li>SP_ERROR_CANT_OPEN_TRACE_FILE\n: <a class=\"el\" href=\"group__error.html#ggafd27986ce4cd9eeaeca8adda83c9eb6badb3af1736912156cbe0b1e39eaeee1c8\">api.h</a>\n</li>\n<li>SP_ERROR_CLIENT_TOO_OLD\n: <a class=\"el\" href=\"group__error.html#ggafd27986ce4cd9eeaeca8adda83c9eb6ba995344026c012b3f59dc73e12c28b1ba\">api.h</a>\n</li>\n<li>SP_ERROR_INBOX_IS_FULL\n: <a class=\"el\" href=\"group__error.html#ggafd27986ce4cd9eeaeca8adda83c9eb6baa4bdf4298c9653549464d21ee528c881\">api.h</a>\n</li>\n<li>SP_ERROR_INDEX_OUT_OF_RANGE\n: <a class=\"el\" href=\"group__error.html#ggafd27986ce4cd9eeaeca8adda83c9eb6ba44b3f132578cbf9a43b5c048efcf63a2\">api.h</a>\n</li>\n<li>SP_ERROR_INVALID_ARGUMENT\n: <a class=\"el\" href=\"group__error.html#ggafd27986ce4cd9eeaeca8adda83c9eb6ba7f8be4d478e51d2b205157c7c538a3e5\">api.h</a>\n</li>\n<li>SP_ERROR_INVALID_DEVICE_ID\n: <a class=\"el\" href=\"group__error.html#ggafd27986ce4cd9eeaeca8adda83c9eb6ba846d94ada9e8db0c2bd5153f5801afa2\">api.h</a>\n</li>\n<li>SP_ERROR_INVALID_INDATA\n: <a class=\"el\" href=\"group__error.html#ggafd27986ce4cd9eeaeca8adda83c9eb6bac9f65a7270391d35342ca9e6c01d519d\">api.h</a>\n</li>\n<li>SP_ERROR_IS_LOADING\n: <a class=\"el\" href=\"group__error.html#ggafd27986ce4cd9eeaeca8adda83c9eb6ba17f54c30d01baedc24547e62ed417cdd\">api.h</a>\n</li>\n<li>SP_ERROR_LASTFM_AUTH_ERROR\n: <a class=\"el\" href=\"group__error.html#ggafd27986ce4cd9eeaeca8adda83c9eb6baf588c0f7a2d8d11acea28ac2a4de43c4\">api.h</a>\n</li>\n<li>SP_ERROR_MISSING_CALLBACK\n: <a class=\"el\" href=\"group__error.html#ggafd27986ce4cd9eeaeca8adda83c9eb6babb1116e69e1d651f9f175dbc8bb5fa32\">api.h</a>\n</li>\n<li>SP_ERROR_NETWORK_DISABLED\n: <a class=\"el\" href=\"group__error.html#ggafd27986ce4cd9eeaeca8adda83c9eb6ba8fda4dd3ee6ac931337a871fbee02978\">api.h</a>\n</li>\n<li>SP_ERROR_NO_CACHE\n: <a class=\"el\" href=\"group__error.html#ggafd27986ce4cd9eeaeca8adda83c9eb6ba3b8851ee3ba2bd7ad1fe377d94ac38c0\">api.h</a>\n</li>\n<li>SP_ERROR_NO_CREDENTIALS\n: <a class=\"el\" href=\"group__error.html#ggafd27986ce4cd9eeaeca8adda83c9eb6ba9ad34b997313d790f142f24e77e78e2d\">api.h</a>\n</li>\n<li>SP_ERROR_NO_STREAM_AVAILABLE\n: <a class=\"el\" href=\"group__error.html#ggafd27986ce4cd9eeaeca8adda83c9eb6ba71307cc7b8460042603f3f322d1096f4\">api.h</a>\n</li>\n<li>SP_ERROR_NO_SUCH_USER\n: <a class=\"el\" href=\"group__error.html#ggafd27986ce4cd9eeaeca8adda83c9eb6baf8ade144869c958de534ecec9f9a36a9\">api.h</a>\n</li>\n<li>SP_ERROR_OFFLINE_DISK_CACHE\n: <a class=\"el\" href=\"group__error.html#ggafd27986ce4cd9eeaeca8adda83c9eb6bae6b9d9b013f1243548e4fbcf961559ff\">api.h</a>\n</li>\n<li>SP_ERROR_OFFLINE_EXPIRED\n: <a class=\"el\" href=\"group__error.html#ggafd27986ce4cd9eeaeca8adda83c9eb6ba7e16a1962fd4de081d73dc4a4e32eb04\">api.h</a>\n</li>\n<li>SP_ERROR_OFFLINE_LICENSE_ERROR\n: <a class=\"el\" href=\"group__error.html#ggafd27986ce4cd9eeaeca8adda83c9eb6ba9149b343017c0dea431839c8b4d9198c\">api.h</a>\n</li>\n<li>SP_ERROR_OFFLINE_LICENSE_LOST\n: <a class=\"el\" href=\"group__error.html#ggafd27986ce4cd9eeaeca8adda83c9eb6ba2c87afb46df21783f172a06b2c25d8f9\">api.h</a>\n</li>\n<li>SP_ERROR_OFFLINE_NOT_ALLOWED\n: <a class=\"el\" href=\"group__error.html#ggafd27986ce4cd9eeaeca8adda83c9eb6bae102b46f4fae3b7b6b34e21ea80d656f\">api.h</a>\n</li>\n<li>SP_ERROR_OFFLINE_TOO_MANY_TRACKS\n: <a class=\"el\" href=\"group__error.html#ggafd27986ce4cd9eeaeca8adda83c9eb6ba32fd1f63fd4dc7ec50bd11791f02953f\">api.h</a>\n</li>\n<li>SP_ERROR_OK\n: <a class=\"el\" href=\"group__error.html#ggafd27986ce4cd9eeaeca8adda83c9eb6ba16cb277dc84328e4b2c0cf6d5a0c0b8d\">api.h</a>\n</li>\n<li>SP_ERROR_OTHER_PERMANENT\n: <a class=\"el\" href=\"group__error.html#ggafd27986ce4cd9eeaeca8adda83c9eb6ba3f68775a5c001bd1de26afdf5ea4e09d\">api.h</a>\n</li>\n<li>SP_ERROR_OTHER_TRANSIENT\n: <a class=\"el\" href=\"group__error.html#ggafd27986ce4cd9eeaeca8adda83c9eb6baf139c18351a543862bd9393ccebc5f91\">api.h</a>\n</li>\n<li>SP_ERROR_PERMISSION_DENIED\n: <a class=\"el\" href=\"group__error.html#ggafd27986ce4cd9eeaeca8adda83c9eb6baaddac1f3b82e905711ab9ffe5b4b0329\">api.h</a>\n</li>\n<li>SP_ERROR_SYSTEM_FAILURE\n: <a class=\"el\" href=\"group__error.html#ggafd27986ce4cd9eeaeca8adda83c9eb6ba73d533e0f25f4ba4cecd6d2e2502b80b\">api.h</a>\n</li>\n<li>SP_ERROR_TRACK_NOT_PLAYABLE\n: <a class=\"el\" href=\"group__error.html#ggafd27986ce4cd9eeaeca8adda83c9eb6ba7b94fe2b53f58d91d4c3cda7bb706ff3\">api.h</a>\n</li>\n<li>SP_ERROR_UNABLE_TO_CONTACT_SERVER\n: <a class=\"el\" href=\"group__error.html#ggafd27986ce4cd9eeaeca8adda83c9eb6ba9d11d66176b6ae95bf00486e9e39866b\">api.h</a>\n</li>\n<li>SP_ERROR_USER_BANNED\n: <a class=\"el\" href=\"group__error.html#ggafd27986ce4cd9eeaeca8adda83c9eb6ba822f4031a82ab428cd04f2ecdc0e757f\">api.h</a>\n</li>\n<li>SP_ERROR_USER_NEEDS_PREMIUM\n: <a class=\"el\" href=\"group__error.html#ggafd27986ce4cd9eeaeca8adda83c9eb6ba96c08adfcda17005c63142cd4e4cd9bb\">api.h</a>\n</li>\n<li>SP_IMAGE_FORMAT_JPEG\n: <a class=\"el\" href=\"group__image.html#gga2cda19baf2460da5e81fb1917f54626ba6263674800bea702c4d913d4b07c135d\">api.h</a>\n</li>\n<li>SP_IMAGE_FORMAT_UNKNOWN\n: <a class=\"el\" href=\"group__image.html#gga2cda19baf2460da5e81fb1917f54626ba2fec8a1b400bd6cd5396b9852e4279b6\">api.h</a>\n</li>\n<li>SP_IMAGE_SIZE_LARGE\n: <a class=\"el\" href=\"group__session.html#gga61bc424465d776af3ceeb69eee2bb492a0a0b624afbb2a66ee3d7954202b89721\">api.h</a>\n</li>\n<li>SP_IMAGE_SIZE_NORMAL\n: <a class=\"el\" href=\"group__session.html#gga61bc424465d776af3ceeb69eee2bb492ad20c808fd1f8180d1f49f643975d1dd7\">api.h</a>\n</li>\n<li>SP_IMAGE_SIZE_SMALL\n: <a class=\"el\" href=\"group__session.html#gga61bc424465d776af3ceeb69eee2bb492ab9340b1bcf2129c3ad1328ea617d547f\">api.h</a>\n</li>\n<li>SP_LINKTYPE_ALBUM\n: <a class=\"el\" href=\"group__link.html#ggabe9611f04086cdbed6e4e6e1fd913b98a7716eb95eed852d08300e6e64febc7f3\">api.h</a>\n</li>\n<li>SP_LINKTYPE_ARTIST\n: <a class=\"el\" href=\"group__link.html#ggabe9611f04086cdbed6e4e6e1fd913b98a4402b3b001aebb39fd55296f83c60b7e\">api.h</a>\n</li>\n<li>SP_LINKTYPE_IMAGE\n: <a class=\"el\" href=\"group__link.html#ggabe9611f04086cdbed6e4e6e1fd913b98a1b20b8e2b8773df47b241dc7d28ea0e8\">api.h</a>\n</li>\n<li>SP_LINKTYPE_INVALID\n: <a class=\"el\" href=\"group__link.html#ggabe9611f04086cdbed6e4e6e1fd913b98a88b0098486cde586b4dcffb623ac6e63\">api.h</a>\n</li>\n<li>SP_LINKTYPE_LOCALTRACK\n: <a class=\"el\" href=\"group__link.html#ggabe9611f04086cdbed6e4e6e1fd913b98a0698cd0123190c7af55daf79bb642805\">api.h</a>\n</li>\n<li>SP_LINKTYPE_PLAYLIST\n: <a class=\"el\" href=\"group__link.html#ggabe9611f04086cdbed6e4e6e1fd913b98a2640ed065a64b6a9f67e71bbeb2af2dd\">api.h</a>\n</li>\n<li>SP_LINKTYPE_PROFILE\n: <a class=\"el\" href=\"group__link.html#ggabe9611f04086cdbed6e4e6e1fd913b98ab7a356adce8b1ea34daf21532c7b50e6\">api.h</a>\n</li>\n<li>SP_LINKTYPE_SEARCH\n: <a class=\"el\" href=\"group__link.html#ggabe9611f04086cdbed6e4e6e1fd913b98ad5909ab9b1cca702163e116b04b6ee8e\">api.h</a>\n</li>\n<li>SP_LINKTYPE_STARRED\n: <a class=\"el\" href=\"group__link.html#ggabe9611f04086cdbed6e4e6e1fd913b98ab649bd86d0fc55ab3fafed3050261353\">api.h</a>\n</li>\n<li>SP_LINKTYPE_TRACK\n: <a class=\"el\" href=\"group__link.html#ggabe9611f04086cdbed6e4e6e1fd913b98a5911dbb7258ed160b2f9c114cef152f1\">api.h</a>\n</li>\n<li>SP_PLAYLIST_OFFLINE_STATUS_DOWNLOADING\n: <a class=\"el\" href=\"group__session.html#gga811fa52ed0fdb5cda732682e27e40417abc999c70761d392b26753708e9a2cfa1\">api.h</a>\n</li>\n<li>SP_PLAYLIST_OFFLINE_STATUS_NO\n: <a class=\"el\" href=\"group__session.html#gga811fa52ed0fdb5cda732682e27e40417abef62e4e3a4af8827fed7fe3aa733ca0\">api.h</a>\n</li>\n<li>SP_PLAYLIST_OFFLINE_STATUS_WAITING\n: <a class=\"el\" href=\"group__session.html#gga811fa52ed0fdb5cda732682e27e40417a7d929bbf4f1df3633b283e39b9c95919\">api.h</a>\n</li>\n<li>SP_PLAYLIST_OFFLINE_STATUS_YES\n: <a class=\"el\" href=\"group__session.html#gga811fa52ed0fdb5cda732682e27e40417affed38ac820e084b96fb48e3d1939584\">api.h</a>\n</li>\n<li>SP_PLAYLIST_TYPE_END_FOLDER\n: <a class=\"el\" href=\"group__session.html#ggafdd7117213605e6f2671c4f289b44609a3ec52ad1d99d8e32e1b9de31e3f5187a\">api.h</a>\n</li>\n<li>SP_PLAYLIST_TYPE_PLACEHOLDER\n: <a class=\"el\" href=\"group__session.html#ggafdd7117213605e6f2671c4f289b44609ad4f860ef76154e3e2c0d9da2f57a2784\">api.h</a>\n</li>\n<li>SP_PLAYLIST_TYPE_PLAYLIST\n: <a class=\"el\" href=\"group__session.html#ggafdd7117213605e6f2671c4f289b44609a6bd6bf9b62018fa9bbf969835c2f3077\">api.h</a>\n</li>\n<li>SP_PLAYLIST_TYPE_START_FOLDER\n: <a class=\"el\" href=\"group__session.html#ggafdd7117213605e6f2671c4f289b44609a4d3266991787f9438deb9de83d9200da\">api.h</a>\n</li>\n<li>SP_RELATION_TYPE_BIDIRECTIONAL\n: <a class=\"el\" href=\"group__user.html#gga6af84143c0622b6fc5539bb1ae111e5ba4bfef63cabd016cf1e6b11347a05d389\">api.h</a>\n</li>\n<li>SP_RELATION_TYPE_NONE\n: <a class=\"el\" href=\"group__user.html#gga6af84143c0622b6fc5539bb1ae111e5bad9805f100828a9d3b64c3cc66f2ac5c1\">api.h</a>\n</li>\n<li>SP_RELATION_TYPE_UNIDIRECTIONAL\n: <a class=\"el\" href=\"group__user.html#gga6af84143c0622b6fc5539bb1ae111e5ba06b2f38745c467e7e362c7744cb74205\">api.h</a>\n</li>\n<li>SP_RELATION_TYPE_UNKNOWN\n: <a class=\"el\" href=\"group__user.html#gga6af84143c0622b6fc5539bb1ae111e5ba18f24164eef0e687b351c2aa6753e35e\">api.h</a>\n</li>\n<li>SP_SAMPLETYPE_INT16_NATIVE_ENDIAN\n: <a class=\"el\" href=\"group__session.html#gga087d21080010768316cfb55d938eb94daa829b269d191cca95ecb02c2bc59da42\">api.h</a>\n</li>\n<li>SP_TOPLIST_REGION_EVERYWHERE\n: <a class=\"el\" href=\"group__toplist.html#gga6fa5cfed2cbb33f2f64542d0b63f6c8da9e9136541401041c7d5c37708b7a927f\">api.h</a>\n</li>\n<li>SP_TOPLIST_REGION_USER\n: <a class=\"el\" href=\"group__toplist.html#gga6fa5cfed2cbb33f2f64542d0b63f6c8da6912eff58c71f5c74b78f48af5305375\">api.h</a>\n</li>\n<li>SP_TOPLIST_TYPE_ALBUMS\n: <a class=\"el\" href=\"group__toplist.html#gga220f32522efb2828e4f8ffb949af234aae8002818ef10eb2c75ec2058ce11cf6b\">api.h</a>\n</li>\n<li>SP_TOPLIST_TYPE_ARTISTS\n: <a class=\"el\" href=\"group__toplist.html#gga220f32522efb2828e4f8ffb949af234aa41523e58badf9e3901beea3f53e5d28e\">api.h</a>\n</li>\n<li>SP_TOPLIST_TYPE_TRACKS\n: <a class=\"el\" href=\"group__toplist.html#gga220f32522efb2828e4f8ffb949af234aa6a85f8384ec77cb9cb5746966b0f0e28\">api.h</a>\n</li>\n<li>SP_TRACK_AVAILABILITY_AVAILABLE\n: <a class=\"el\" href=\"group__session.html#ggad7d9465769597b2a379ac704099adfdfa3b837ba6d740b5650b0113734a3b2ff7\">api.h</a>\n</li>\n<li>SP_TRACK_AVAILABILITY_BANNED_BY_ARTIST\n: <a class=\"el\" href=\"group__session.html#ggad7d9465769597b2a379ac704099adfdfaeb5d63e89c543f513cd3054969e50914\">api.h</a>\n</li>\n<li>SP_TRACK_AVAILABILITY_NOT_STREAMABLE\n: <a class=\"el\" href=\"group__session.html#ggad7d9465769597b2a379ac704099adfdfae7b2cfafa10288ecc50df97621bbe940\">api.h</a>\n</li>\n<li>SP_TRACK_AVAILABILITY_UNAVAILABLE\n: <a class=\"el\" href=\"group__session.html#ggad7d9465769597b2a379ac704099adfdfa44bc1e6f138910b3f8dbd309325e0077\">api.h</a>\n</li>\n<li>SP_TRACK_OFFLINE_DONE\n: <a class=\"el\" href=\"group__session.html#ggaeaa41aad3c0047409996a6ec3b03203fac54d46cbc73de7686a1ad8daf269532a\">api.h</a>\n</li>\n<li>SP_TRACK_OFFLINE_DONE_EXPIRED\n: <a class=\"el\" href=\"group__session.html#ggaeaa41aad3c0047409996a6ec3b03203fa00fe430030fb6a8a49a46c11cca7326c\">api.h</a>\n</li>\n<li>SP_TRACK_OFFLINE_DONE_RESYNC\n: <a class=\"el\" href=\"group__session.html#ggaeaa41aad3c0047409996a6ec3b03203fa5f3e19627de4509ae4a3864fd29edee6\">api.h</a>\n</li>\n<li>SP_TRACK_OFFLINE_DOWNLOADING\n: <a class=\"el\" href=\"group__session.html#ggaeaa41aad3c0047409996a6ec3b03203fa7dcf6dfc56a8421200451d07a476f370\">api.h</a>\n</li>\n<li>SP_TRACK_OFFLINE_ERROR\n: <a class=\"el\" href=\"group__session.html#ggaeaa41aad3c0047409996a6ec3b03203fa86618798c266540bdc889dd037a52631\">api.h</a>\n</li>\n<li>SP_TRACK_OFFLINE_LIMIT_EXCEEDED\n: <a class=\"el\" href=\"group__session.html#ggaeaa41aad3c0047409996a6ec3b03203fa405a9b7a3fa489ad2dadbb108794e247\">api.h</a>\n</li>\n<li>SP_TRACK_OFFLINE_NO\n: <a class=\"el\" href=\"group__session.html#ggaeaa41aad3c0047409996a6ec3b03203faad1a1cba82ce9f9be678f4d1042eddec\">api.h</a>\n</li>\n<li>SP_TRACK_OFFLINE_WAITING\n: <a class=\"el\" href=\"group__session.html#ggaeaa41aad3c0047409996a6ec3b03203fa1fdd2a518dcdc072cfca27a0ca4f2581\">api.h</a>\n</li>\n</ul>\n</div>\n<hr size=\"1\"><address style=\"text-align: right;\"><small>\nGenerated on Wed Jun 13 2012 14:22:40.<br>\nCopyright &copy; 2006&ndash;2012 Spotify Ltd</small></address>\n</body>\n</html>\n"
  },
  {
    "path": "libspotify/docs/html/globals_func.html",
    "content": "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\n<html xmlns=\"http://www.w3.org/1999/xhtml\">\n<head>\n<meta http-equiv=\"Content-Type\" content=\"text/xhtml;charset=UTF-8\"/>\n<title>libspotify: Data Fields</title>\n<link href=\"tabs.css\" rel=\"stylesheet\" type=\"text/css\"/>\n<link href=\"doxygen.css\" rel=\"stylesheet\" type=\"text/css\"/>\n</head>\n<body>\n<!-- Generated by Doxygen 1.7.1 -->\n<div class=\"navigation\" id=\"top\">\n  <div class=\"tabs\">\n    <ul class=\"tablist\">\n      <li><a href=\"index.html\"><span>Main&nbsp;Page</span></a></li>\n      <li><a href=\"modules.html\"><span>Modules</span></a></li>\n      <li><a href=\"annotated.html\"><span>Data&nbsp;Structures</span></a></li>\n      <li class=\"current\"><a href=\"files.html\"><span>Files</span></a></li>\n      <li><a href=\"examples.html\"><span>Examples</span></a></li>\n    </ul>\n  </div>\n  <div class=\"tabs2\">\n    <ul class=\"tablist\">\n      <li><a href=\"files.html\"><span>File&nbsp;List</span></a></li>\n      <li class=\"current\"><a href=\"globals.html\"><span>Globals</span></a></li>\n    </ul>\n  </div>\n  <div class=\"tabs2\">\n    <ul class=\"tablist\">\n      <li><a href=\"globals.html\"><span>All</span></a></li>\n      <li class=\"current\"><a href=\"globals_func.html\"><span>Functions</span></a></li>\n      <li><a href=\"globals_type.html\"><span>Typedefs</span></a></li>\n      <li><a href=\"globals_enum.html\"><span>Enumerations</span></a></li>\n      <li><a href=\"globals_eval.html\"><span>Enumerator</span></a></li>\n      <li><a href=\"globals_defs.html\"><span>Defines</span></a></li>\n    </ul>\n  </div>\n  <div class=\"tabs3\">\n    <ul class=\"tablist\">\n      <li class=\"current\"><a href=\"globals_func.html#index_s\"><span>s</span></a></li>\n    </ul>\n  </div>\n</div>\n<div class=\"contents\">\n&nbsp;\n\n<h3><a class=\"anchor\" id=\"index_s\"></a>- s -</h3><ul>\n<li>sp_album_add_ref()\n: <a class=\"el\" href=\"group__album.html#ga08192dd38d1c628f7b51615fffa33017\">api.h</a>\n</li>\n<li>sp_album_artist()\n: <a class=\"el\" href=\"group__album.html#ga42309972141dab10c32d741d357c01de\">api.h</a>\n</li>\n<li>sp_album_cover()\n: <a class=\"el\" href=\"group__album.html#ga6616ef3df724af185c5eb58e8a0fb808\">api.h</a>\n</li>\n<li>sp_album_is_available()\n: <a class=\"el\" href=\"group__album.html#ga89eb8dc73a76f5e0509b1066426495f7\">api.h</a>\n</li>\n<li>sp_album_is_loaded()\n: <a class=\"el\" href=\"group__album.html#ga46fbfa98be12c2f4067d5e679552cfb9\">api.h</a>\n</li>\n<li>sp_album_name()\n: <a class=\"el\" href=\"group__album.html#ga0e828c991a8184d60026513f944e19ad\">api.h</a>\n</li>\n<li>sp_album_release()\n: <a class=\"el\" href=\"group__album.html#ga5c6e49d04ffb05c722db5e78c9434b88\">api.h</a>\n</li>\n<li>sp_album_type()\n: <a class=\"el\" href=\"group__album.html#ga8dceb04a62bdb3ffc112ed0efc359e51\">api.h</a>\n</li>\n<li>sp_album_year()\n: <a class=\"el\" href=\"group__album.html#ga2aadf934b0af43c3ef6ee98b6a8065fd\">api.h</a>\n</li>\n<li>sp_albumbrowse_add_ref()\n: <a class=\"el\" href=\"group__albumbrowse.html#ga1afd6a10febf31a61cf356673cb34bef\">api.h</a>\n</li>\n<li>sp_albumbrowse_album()\n: <a class=\"el\" href=\"group__albumbrowse.html#gaf0dadfc4edb48a3558b606e30e8bedfa\">api.h</a>\n</li>\n<li>sp_albumbrowse_artist()\n: <a class=\"el\" href=\"group__albumbrowse.html#ga4f835537a65bcac9ec52cef1058a44bc\">api.h</a>\n</li>\n<li>sp_albumbrowse_backend_request_duration()\n: <a class=\"el\" href=\"group__albumbrowse.html#ga2f1e1049065e8c090c010f8e43061bd4\">api.h</a>\n</li>\n<li>sp_albumbrowse_copyright()\n: <a class=\"el\" href=\"group__albumbrowse.html#ga34b205daa2960e8d02a6e1accd80ab92\">api.h</a>\n</li>\n<li>sp_albumbrowse_create()\n: <a class=\"el\" href=\"group__albumbrowse.html#gaf1bc3042e748efea5ca7ac159e5cbfbe\">api.h</a>\n</li>\n<li>sp_albumbrowse_error()\n: <a class=\"el\" href=\"group__albumbrowse.html#ga153417eee319e7711b66503f88fba88b\">api.h</a>\n</li>\n<li>sp_albumbrowse_is_loaded()\n: <a class=\"el\" href=\"group__albumbrowse.html#gad618d2752eb55173ab373d1407971960\">api.h</a>\n</li>\n<li>sp_albumbrowse_num_copyrights()\n: <a class=\"el\" href=\"group__albumbrowse.html#gab53fa74ee1958dad5186be09e70ddc4a\">api.h</a>\n</li>\n<li>sp_albumbrowse_num_tracks()\n: <a class=\"el\" href=\"group__albumbrowse.html#ga3fb91de745ca07d3801a57288f2d9da7\">api.h</a>\n</li>\n<li>sp_albumbrowse_release()\n: <a class=\"el\" href=\"group__albumbrowse.html#gabdd5a4e3b2098166b67e35979f59613d\">api.h</a>\n</li>\n<li>sp_albumbrowse_review()\n: <a class=\"el\" href=\"group__albumbrowse.html#ga868f3f3263f5033ae1fba60f403be712\">api.h</a>\n</li>\n<li>sp_albumbrowse_track()\n: <a class=\"el\" href=\"group__albumbrowse.html#gad3c8df4b75158bba2c06aaefa74c5aa1\">api.h</a>\n</li>\n<li>sp_artist_add_ref()\n: <a class=\"el\" href=\"group__artist.html#gac70d7467f580aa497d1a5d610e06d273\">api.h</a>\n</li>\n<li>sp_artist_is_loaded()\n: <a class=\"el\" href=\"group__artist.html#gafc98f5093184a7ac7ce608302b0971ea\">api.h</a>\n</li>\n<li>sp_artist_name()\n: <a class=\"el\" href=\"group__artist.html#gad2895555bb48514986823733a7afe5e2\">api.h</a>\n</li>\n<li>sp_artist_portrait()\n: <a class=\"el\" href=\"group__artist.html#ga87d366ac7479c717005c2c059d5f2be9\">api.h</a>\n</li>\n<li>sp_artist_release()\n: <a class=\"el\" href=\"group__artist.html#ga7b0da8f7ce09454bd0821d06d52e2d12\">api.h</a>\n</li>\n<li>sp_artistbrowse_add_ref()\n: <a class=\"el\" href=\"group__artistbrowse.html#ga69fc2e1d2d5e8d91a724486cbfd0c4dc\">api.h</a>\n</li>\n<li>sp_artistbrowse_album()\n: <a class=\"el\" href=\"group__artistbrowse.html#ga5b36c9a34876beea8fda8674b93d4fd3\">api.h</a>\n</li>\n<li>sp_artistbrowse_artist()\n: <a class=\"el\" href=\"group__artistbrowse.html#ga5f6a046b2bd261d7628582b986a9019f\">api.h</a>\n</li>\n<li>sp_artistbrowse_backend_request_duration()\n: <a class=\"el\" href=\"group__artistbrowse.html#gadce357748b82abce8a7b093882850fdb\">api.h</a>\n</li>\n<li>sp_artistbrowse_biography()\n: <a class=\"el\" href=\"group__artistbrowse.html#ga8b93b9e5630662855f35694280ba4d2b\">api.h</a>\n</li>\n<li>sp_artistbrowse_create()\n: <a class=\"el\" href=\"group__artistbrowse.html#ga8dd8364b2fcd29c846209660bd9a69b2\">api.h</a>\n</li>\n<li>sp_artistbrowse_error()\n: <a class=\"el\" href=\"group__artistbrowse.html#ga203e757088ff7a5098f16a1367da25d2\">api.h</a>\n</li>\n<li>sp_artistbrowse_is_loaded()\n: <a class=\"el\" href=\"group__artistbrowse.html#ga966b0f59e7b2b3d0037e44bb49dcdabc\">api.h</a>\n</li>\n<li>sp_artistbrowse_num_albums()\n: <a class=\"el\" href=\"group__artistbrowse.html#gaf0055361abd53425d89a4636a32b5c83\">api.h</a>\n</li>\n<li>sp_artistbrowse_num_portraits()\n: <a class=\"el\" href=\"group__artistbrowse.html#ga98dc47d36d2789999bfe62707c5041d7\">api.h</a>\n</li>\n<li>sp_artistbrowse_num_similar_artists()\n: <a class=\"el\" href=\"group__artistbrowse.html#ga2559638742416ac621af0e919e017d17\">api.h</a>\n</li>\n<li>sp_artistbrowse_num_tophit_tracks()\n: <a class=\"el\" href=\"group__artistbrowse.html#ga0c26782796af954300ce92fddea97637\">api.h</a>\n</li>\n<li>sp_artistbrowse_num_tracks()\n: <a class=\"el\" href=\"group__artistbrowse.html#ga8c862caa2234125ffcc4e93287b1e029\">api.h</a>\n</li>\n<li>sp_artistbrowse_portrait()\n: <a class=\"el\" href=\"group__artistbrowse.html#ga5f164b2f9609a7bf2c89b3a1407ec239\">api.h</a>\n</li>\n<li>sp_artistbrowse_release()\n: <a class=\"el\" href=\"group__artistbrowse.html#ga14626a4f6a60b1caf61cb54c26783671\">api.h</a>\n</li>\n<li>sp_artistbrowse_similar_artist()\n: <a class=\"el\" href=\"group__artistbrowse.html#gac60ef4f9e006a920f1d72b6098743fbc\">api.h</a>\n</li>\n<li>sp_artistbrowse_tophit_track()\n: <a class=\"el\" href=\"group__artistbrowse.html#ga5da55f43def03fe9f0d2c8b252b9755a\">api.h</a>\n</li>\n<li>sp_artistbrowse_track()\n: <a class=\"el\" href=\"group__artistbrowse.html#ga45d28771a856f935dc40ab40e27dec4c\">api.h</a>\n</li>\n<li>sp_build_id()\n: <a class=\"el\" href=\"api_8h.html#a181d0940997cb8b69869449cd826cf88\">api.h</a>\n</li>\n<li>sp_error_message()\n: <a class=\"el\" href=\"group__error.html#ga983dee341d3c2008830513b7cffe7bf3\">api.h</a>\n</li>\n<li>sp_image_add_load_callback()\n: <a class=\"el\" href=\"group__image.html#gaa414f26ad1b9095645a83361597c92ce\">api.h</a>\n</li>\n<li>sp_image_add_ref()\n: <a class=\"el\" href=\"group__image.html#ga98c93dbedfb182243742131a5224b83b\">api.h</a>\n</li>\n<li>sp_image_create()\n: <a class=\"el\" href=\"group__image.html#gaf29e89f45945db2b3667bf9db4279c33\">api.h</a>\n</li>\n<li>sp_image_create_from_link()\n: <a class=\"el\" href=\"group__image.html#ga70fb25cd2b0caaf15f637f36e75524b9\">api.h</a>\n</li>\n<li>sp_image_data()\n: <a class=\"el\" href=\"group__image.html#ga03700a7dfa90bfc8200b89f15acd91aa\">api.h</a>\n</li>\n<li>sp_image_error()\n: <a class=\"el\" href=\"group__image.html#gae40103df87426b346e0d0413d8d3b0ff\">api.h</a>\n</li>\n<li>sp_image_format()\n: <a class=\"el\" href=\"group__image.html#ga04448e81ca4916ba7ed223d0d817e803\">api.h</a>\n</li>\n<li>sp_image_image_id()\n: <a class=\"el\" href=\"group__image.html#ga0ee0b98cc25c995fe208a992cc87d145\">api.h</a>\n</li>\n<li>sp_image_is_loaded()\n: <a class=\"el\" href=\"group__image.html#ga45312b1b9b5e5565485d61a8f0300e18\">api.h</a>\n</li>\n<li>sp_image_release()\n: <a class=\"el\" href=\"group__image.html#ga3df9af5f68b18df5a598b7510e9b587f\">api.h</a>\n</li>\n<li>sp_image_remove_load_callback()\n: <a class=\"el\" href=\"group__image.html#gaaee68c65d9eab3499f2b6be5d048d6ba\">api.h</a>\n</li>\n<li>sp_inbox_add_ref()\n: <a class=\"el\" href=\"group__inbox.html#gadb6b607bc26b9d362de4da09ec1c864f\">api.h</a>\n</li>\n<li>sp_inbox_error()\n: <a class=\"el\" href=\"group__inbox.html#gaa452e9fe1fa7c9e2c780d28ce2ed63c5\">api.h</a>\n</li>\n<li>sp_inbox_post_tracks()\n: <a class=\"el\" href=\"group__inbox.html#gaee29e747ca10b36597d91689ae074aa2\">api.h</a>\n</li>\n<li>sp_inbox_release()\n: <a class=\"el\" href=\"group__inbox.html#ga73659a65af92d30e4ac1cf3e06e74a0a\">api.h</a>\n</li>\n<li>sp_link_add_ref()\n: <a class=\"el\" href=\"group__link.html#gac5a808b15bceed41508bd3863c8f4b3b\">api.h</a>\n</li>\n<li>sp_link_as_album()\n: <a class=\"el\" href=\"group__link.html#gaafa98628d0abadcca27dd3b227c7337b\">api.h</a>\n</li>\n<li>sp_link_as_artist()\n: <a class=\"el\" href=\"group__link.html#gab32979d26dcf68936202fa7aed7b6e49\">api.h</a>\n</li>\n<li>sp_link_as_string()\n: <a class=\"el\" href=\"group__link.html#ga9f169be53f098adcf12f7a10b8bd3ef7\">api.h</a>\n</li>\n<li>sp_link_as_track()\n: <a class=\"el\" href=\"group__link.html#ga2560687997d7ce0fbf4f05251d87d32a\">api.h</a>\n</li>\n<li>sp_link_as_track_and_offset()\n: <a class=\"el\" href=\"group__link.html#ga80f6f752832f76c268c0bfd3ca45e6d2\">api.h</a>\n</li>\n<li>sp_link_as_user()\n: <a class=\"el\" href=\"group__link.html#ga3e29975f47fc0a51be813b4774a3d6f3\">api.h</a>\n</li>\n<li>sp_link_create_from_album()\n: <a class=\"el\" href=\"group__link.html#ga040627b0df84425947c82cd8890122ad\">api.h</a>\n</li>\n<li>sp_link_create_from_album_cover()\n: <a class=\"el\" href=\"group__link.html#gaa87e346c29f1077d7a62c364719d4a55\">api.h</a>\n</li>\n<li>sp_link_create_from_artist()\n: <a class=\"el\" href=\"group__link.html#ga3196ce9de3da4f1d5944a0b58bd80540\">api.h</a>\n</li>\n<li>sp_link_create_from_artist_portrait()\n: <a class=\"el\" href=\"group__link.html#gaafb25ee14bfb27f9cbbab1b039d4d225\">api.h</a>\n</li>\n<li>sp_link_create_from_artistbrowse_portrait()\n: <a class=\"el\" href=\"group__link.html#ga32218fbd912ddddbb749cb42a72b6bcd\">api.h</a>\n</li>\n<li>sp_link_create_from_image()\n: <a class=\"el\" href=\"group__link.html#gaa85fbea312127db44685b7e9dc492042\">api.h</a>\n</li>\n<li>sp_link_create_from_playlist()\n: <a class=\"el\" href=\"group__link.html#ga805392bfa8e526eebedc1cf5a7bcae0f\">api.h</a>\n</li>\n<li>sp_link_create_from_search()\n: <a class=\"el\" href=\"group__link.html#ga95c97ba4de9c4040047276ad618a108e\">api.h</a>\n</li>\n<li>sp_link_create_from_string()\n: <a class=\"el\" href=\"group__link.html#gaea9c39f35f7986fc9fed4584fa211127\">api.h</a>\n</li>\n<li>sp_link_create_from_track()\n: <a class=\"el\" href=\"group__link.html#ga82c29419ce70e2b504670e3d45167d5d\">api.h</a>\n</li>\n<li>sp_link_create_from_user()\n: <a class=\"el\" href=\"group__link.html#gaaa78b1750179c17f8152408cea43efef\">api.h</a>\n</li>\n<li>sp_link_release()\n: <a class=\"el\" href=\"group__link.html#ga2b06ab16d1f6436cd8d36dbff2b5c022\">api.h</a>\n</li>\n<li>sp_link_type()\n: <a class=\"el\" href=\"group__link.html#ga6140f924c696d53469bb8930cd53e1e6\">api.h</a>\n</li>\n<li>sp_localtrack_create()\n: <a class=\"el\" href=\"group__track.html#ga0fb814ef23636fdecda64e3a63b15a23\">api.h</a>\n</li>\n<li>sp_offline_num_playlists()\n: <a class=\"el\" href=\"group__session.html#gad6cee58fa44453b7a4fd2ae2266df055\">api.h</a>\n</li>\n<li>sp_offline_sync_get_status()\n: <a class=\"el\" href=\"group__session.html#ga02525cd659a34728047cd3801049e822\">api.h</a>\n</li>\n<li>sp_offline_time_left()\n: <a class=\"el\" href=\"group__session.html#gac36816dc42825db9a5a2fbd2694f20af\">api.h</a>\n</li>\n<li>sp_offline_tracks_to_sync()\n: <a class=\"el\" href=\"group__session.html#gaf535124b4208c279cb98a061834e6411\">api.h</a>\n</li>\n<li>sp_playlist_add_callbacks()\n: <a class=\"el\" href=\"group__playlist.html#gab15fca12d387c69b4998a4d2b48e5b32\">api.h</a>\n</li>\n<li>sp_playlist_add_ref()\n: <a class=\"el\" href=\"group__playlist.html#gacb10979add5a954e5c1600ef9c5b17a8\">api.h</a>\n</li>\n<li>sp_playlist_add_tracks()\n: <a class=\"el\" href=\"group__playlist.html#ga2344a47133f7f0aed0a67e154ecc4dc4\">api.h</a>\n</li>\n<li>sp_playlist_create()\n: <a class=\"el\" href=\"group__playlist.html#ga342a6a0cfe10531ef7cb3c6629c1e8e7\">api.h</a>\n</li>\n<li>sp_playlist_get_description()\n: <a class=\"el\" href=\"group__playlist.html#gab1d8e0ee9b436ecbb104bbd6cc0665be\">api.h</a>\n</li>\n<li>sp_playlist_get_image()\n: <a class=\"el\" href=\"group__playlist.html#ga409cb6b2a88db7242ec939b6644e8c30\">api.h</a>\n</li>\n<li>sp_playlist_get_offline_download_completed()\n: <a class=\"el\" href=\"group__playlist.html#ga83ca1a25f50834f8e6f8ee1e883a8c6e\">api.h</a>\n</li>\n<li>sp_playlist_get_offline_status()\n: <a class=\"el\" href=\"group__playlist.html#ga7170157af21445c37a21a2241f91ff06\">api.h</a>\n</li>\n<li>sp_playlist_has_pending_changes()\n: <a class=\"el\" href=\"group__playlist.html#gaf0e39b5969259d10625eb398af0f3f43\">api.h</a>\n</li>\n<li>sp_playlist_is_collaborative()\n: <a class=\"el\" href=\"group__playlist.html#ga8ad160f654f02f13690568070dd57353\">api.h</a>\n</li>\n<li>sp_playlist_is_in_ram()\n: <a class=\"el\" href=\"group__playlist.html#ga28456d1242693c6d890516dc782ab3ec\">api.h</a>\n</li>\n<li>sp_playlist_is_loaded()\n: <a class=\"el\" href=\"group__playlist.html#gaee8ea6c07dfdca3397e27b278fa4870a\">api.h</a>\n</li>\n<li>sp_playlist_name()\n: <a class=\"el\" href=\"group__playlist.html#ga61b7e33cc1aedb4e31a2af75ae0ac8cc\">api.h</a>\n</li>\n<li>sp_playlist_num_subscribers()\n: <a class=\"el\" href=\"group__playlist.html#ga967ad87f0db702513ecda82546f667c5\">api.h</a>\n</li>\n<li>sp_playlist_num_tracks()\n: <a class=\"el\" href=\"group__playlist.html#ga684a3acc60f99b3b26488ed813ee5d23\">api.h</a>\n</li>\n<li>sp_playlist_owner()\n: <a class=\"el\" href=\"group__playlist.html#gac3e4295d3353eb9998402aedfdbd55de\">api.h</a>\n</li>\n<li>sp_playlist_release()\n: <a class=\"el\" href=\"group__playlist.html#gacb9250eb530869b039541a8b62dfab6c\">api.h</a>\n</li>\n<li>sp_playlist_remove_callbacks()\n: <a class=\"el\" href=\"group__playlist.html#ga7fcbf909a0fa8bf25f0b1d1e7dd0e160\">api.h</a>\n</li>\n<li>sp_playlist_remove_tracks()\n: <a class=\"el\" href=\"group__playlist.html#gabd62cd7ff9484b4c31ff7f159ec41b6a\">api.h</a>\n</li>\n<li>sp_playlist_rename()\n: <a class=\"el\" href=\"group__playlist.html#gad6c3880c514353e204fdd90830b516ec\">api.h</a>\n</li>\n<li>sp_playlist_reorder_tracks()\n: <a class=\"el\" href=\"group__playlist.html#ga90ffd8c9fc6abc7375e89f4cb49adb11\">api.h</a>\n</li>\n<li>sp_playlist_set_autolink_tracks()\n: <a class=\"el\" href=\"group__playlist.html#ga0bde47f340e0cd590a78007c6af69307\">api.h</a>\n</li>\n<li>sp_playlist_set_collaborative()\n: <a class=\"el\" href=\"group__playlist.html#gad15410bcc2ebd986adabda865830bce4\">api.h</a>\n</li>\n<li>sp_playlist_set_in_ram()\n: <a class=\"el\" href=\"group__playlist.html#gaf6ca8a349bdd982f6c8dda52ed691017\">api.h</a>\n</li>\n<li>sp_playlist_set_offline_mode()\n: <a class=\"el\" href=\"group__playlist.html#ga784f648f9cc431ef3b51f3491c2f169f\">api.h</a>\n</li>\n<li>sp_playlist_subscribers()\n: <a class=\"el\" href=\"group__playlist.html#gad49f491babc475f8d4aeea1b4452ff8b\">api.h</a>\n</li>\n<li>sp_playlist_subscribers_free()\n: <a class=\"el\" href=\"group__playlist.html#gae7754b74b1c3c8f5222ca43b6608ce6a\">api.h</a>\n</li>\n<li>sp_playlist_track()\n: <a class=\"el\" href=\"group__playlist.html#ga7a03854fe6072476306780d23c6cac16\">api.h</a>\n</li>\n<li>sp_playlist_track_create_time()\n: <a class=\"el\" href=\"group__playlist.html#gab8e77f8d63e787f8aa1a066d74daa74c\">api.h</a>\n</li>\n<li>sp_playlist_track_creator()\n: <a class=\"el\" href=\"group__playlist.html#ga80fcd9e7b40c791433c07d66e2ad432a\">api.h</a>\n</li>\n<li>sp_playlist_track_message()\n: <a class=\"el\" href=\"group__playlist.html#ga6887b9dabb30a060b10bdb75f8b3f971\">api.h</a>\n</li>\n<li>sp_playlist_track_seen()\n: <a class=\"el\" href=\"group__playlist.html#gab9e00ee5bc6b5dc0b3d58cbdb32c0c7b\">api.h</a>\n</li>\n<li>sp_playlist_track_set_seen()\n: <a class=\"el\" href=\"group__playlist.html#ga69f5cc1bdd7dbdcdb476a7b1d2b7834d\">api.h</a>\n</li>\n<li>sp_playlist_update_subscribers()\n: <a class=\"el\" href=\"group__playlist.html#ga9ebbf147230b3ca98b68e556cf24e6bd\">api.h</a>\n</li>\n<li>sp_playlistcontainer_add_callbacks()\n: <a class=\"el\" href=\"group__playlist.html#ga1976cb49c391cdd2dbe7c40d1bc71570\">api.h</a>\n</li>\n<li>sp_playlistcontainer_add_folder()\n: <a class=\"el\" href=\"group__playlist.html#ga0862502eea52fc5f2465ebad6fd98796\">api.h</a>\n</li>\n<li>sp_playlistcontainer_add_new_playlist()\n: <a class=\"el\" href=\"group__playlist.html#ga840b82b1074a7ca1c9eacd351bed24c2\">api.h</a>\n</li>\n<li>sp_playlistcontainer_add_playlist()\n: <a class=\"el\" href=\"group__playlist.html#ga87699479087915b741ceef4eebe69ad8\">api.h</a>\n</li>\n<li>sp_playlistcontainer_add_ref()\n: <a class=\"el\" href=\"group__playlist.html#ga2138c537a6ebcd35a01eea54d0dd1e8f\">api.h</a>\n</li>\n<li>sp_playlistcontainer_clear_unseen_tracks()\n: <a class=\"el\" href=\"group__playlist.html#gadaad604c35e543363e1dd5b23c462db0\">api.h</a>\n</li>\n<li>sp_playlistcontainer_get_unseen_tracks()\n: <a class=\"el\" href=\"group__playlist.html#gad9e11b45843ee4a147b43038a2e55f13\">api.h</a>\n</li>\n<li>sp_playlistcontainer_is_loaded()\n: <a class=\"el\" href=\"group__playlist.html#gae23cb67b4b26bca663034997c4418fa8\">api.h</a>\n</li>\n<li>sp_playlistcontainer_move_playlist()\n: <a class=\"el\" href=\"group__playlist.html#gad9be708159957d4c1e5ef905550808c5\">api.h</a>\n</li>\n<li>sp_playlistcontainer_num_playlists()\n: <a class=\"el\" href=\"group__playlist.html#ga7a1cbf558b2b364b8249d4ce432df700\">api.h</a>\n</li>\n<li>sp_playlistcontainer_owner()\n: <a class=\"el\" href=\"group__playlist.html#gad4fc67d1386dd637f778f4e735a36894\">api.h</a>\n</li>\n<li>sp_playlistcontainer_playlist()\n: <a class=\"el\" href=\"group__playlist.html#ga5ddd8c8064c281a14c6fd7877f522dc6\">api.h</a>\n</li>\n<li>sp_playlistcontainer_playlist_folder_id()\n: <a class=\"el\" href=\"group__playlist.html#ga6939f9db71199612fc5a19d395e3a7f8\">api.h</a>\n</li>\n<li>sp_playlistcontainer_playlist_folder_name()\n: <a class=\"el\" href=\"group__playlist.html#ga852e5f5bcd4520be2e3d6d5d94def44a\">api.h</a>\n</li>\n<li>sp_playlistcontainer_playlist_type()\n: <a class=\"el\" href=\"group__playlist.html#ga79286860a3eeada495e97c5ad1fd7ebf\">api.h</a>\n</li>\n<li>sp_playlistcontainer_release()\n: <a class=\"el\" href=\"group__playlist.html#ga0311c7c3c4f26028e5edd4aacb36dbf8\">api.h</a>\n</li>\n<li>sp_playlistcontainer_remove_callbacks()\n: <a class=\"el\" href=\"group__playlist.html#gafb5242b8f0f9964cec29d32f4d6c1164\">api.h</a>\n</li>\n<li>sp_playlistcontainer_remove_playlist()\n: <a class=\"el\" href=\"group__playlist.html#ga1ae1d51c4305940ae5c5c98c12be0afc\">api.h</a>\n</li>\n<li>sp_search_add_ref()\n: <a class=\"el\" href=\"group__search.html#ga92e45a5edb1e33e64fdb857bd8eb9ad5\">api.h</a>\n</li>\n<li>sp_search_album()\n: <a class=\"el\" href=\"group__search.html#ga4ba7723e70db0c6a4569c4bcd44f0e98\">api.h</a>\n</li>\n<li>sp_search_artist()\n: <a class=\"el\" href=\"group__search.html#ga79b3d532d5a20a3b2bf2a087eead7888\">api.h</a>\n</li>\n<li>sp_search_create()\n: <a class=\"el\" href=\"group__search.html#ga2f64dfbcc1313e7d5179998cb28208d4\">api.h</a>\n</li>\n<li>sp_search_did_you_mean()\n: <a class=\"el\" href=\"group__search.html#ga8561c1da8b93ecdc8f2d325a9d19199b\">api.h</a>\n</li>\n<li>sp_search_error()\n: <a class=\"el\" href=\"group__search.html#ga7cf655e37a823f952d30270d4fb60f10\">api.h</a>\n</li>\n<li>sp_search_is_loaded()\n: <a class=\"el\" href=\"group__search.html#ga70e8c404d8c7ce0bbef70c2b274417cd\">api.h</a>\n</li>\n<li>sp_search_num_albums()\n: <a class=\"el\" href=\"group__search.html#ga0c456a6396c4c05fbc8677ea641ef1f7\">api.h</a>\n</li>\n<li>sp_search_num_artists()\n: <a class=\"el\" href=\"group__search.html#gabd375a613c2dadecad8c13f8aca6f2d3\">api.h</a>\n</li>\n<li>sp_search_num_playlists()\n: <a class=\"el\" href=\"group__search.html#gaa9f007f439d8241bf632f9abb8d926c9\">api.h</a>\n</li>\n<li>sp_search_num_tracks()\n: <a class=\"el\" href=\"group__search.html#ga1dd18cf7b3b3b7f4bf6e92a2140378d0\">api.h</a>\n</li>\n<li>sp_search_playlist()\n: <a class=\"el\" href=\"group__search.html#ga4175fba17f355b1c0bd361357181ea35\">api.h</a>\n</li>\n<li>sp_search_playlist_image_uri()\n: <a class=\"el\" href=\"group__search.html#gac4463fab4ea25e0a5d5079c959a1781c\">api.h</a>\n</li>\n<li>sp_search_playlist_name()\n: <a class=\"el\" href=\"group__search.html#ga933cd5d5a0ccca9906082ca4549a4ed7\">api.h</a>\n</li>\n<li>sp_search_playlist_uri()\n: <a class=\"el\" href=\"group__search.html#ga0071a3d30f0f0c4e477bf923e9014ff5\">api.h</a>\n</li>\n<li>sp_search_query()\n: <a class=\"el\" href=\"group__search.html#ga127e9c2bf98e3602ecfc2926b9d242bf\">api.h</a>\n</li>\n<li>sp_search_release()\n: <a class=\"el\" href=\"group__search.html#ga4e01d43067d9f8c533c985f90143821b\">api.h</a>\n</li>\n<li>sp_search_total_albums()\n: <a class=\"el\" href=\"group__search.html#gaafd3b228adbc028937383d0d45730581\">api.h</a>\n</li>\n<li>sp_search_total_artists()\n: <a class=\"el\" href=\"group__search.html#ga305a4118625e0f70cfb14161a0112fd5\">api.h</a>\n</li>\n<li>sp_search_total_playlists()\n: <a class=\"el\" href=\"group__search.html#ga2e286415a6ba8dbf85ea677906f2798c\">api.h</a>\n</li>\n<li>sp_search_total_tracks()\n: <a class=\"el\" href=\"group__search.html#gab4e50582c517b4639fd1afd6fb011587\">api.h</a>\n</li>\n<li>sp_search_track()\n: <a class=\"el\" href=\"group__search.html#gae9da7ca59ce0bbd73f7bcef4e15c4da8\">api.h</a>\n</li>\n<li>sp_session_connectionstate()\n: <a class=\"el\" href=\"group__session.html#ga34a7c9527705ab7d23b742006d81ea35\">api.h</a>\n</li>\n<li>sp_session_create()\n: <a class=\"el\" href=\"group__session.html#gaf2891f2daced4ff6da84219d6376b3aa\">api.h</a>\n</li>\n<li>sp_session_flush_caches()\n: <a class=\"el\" href=\"group__session.html#ga34005bb06ee3de8ee4221597a0335cca\">api.h</a>\n</li>\n<li>sp_session_forget_me()\n: <a class=\"el\" href=\"group__session.html#ga61e6b796d9e07682c018e888b901a191\">api.h</a>\n</li>\n<li>sp_session_get_volume_normalization()\n: <a class=\"el\" href=\"group__session.html#ga7913df06394360f255c77fb87af0f1fe\">api.h</a>\n</li>\n<li>sp_session_inbox_create()\n: <a class=\"el\" href=\"group__session.html#gac72ccb51031c846101134b73195bb9ec\">api.h</a>\n</li>\n<li>sp_session_is_private_session()\n: <a class=\"el\" href=\"group__session.html#ga72702ee06bc96c074804388d24344149\">api.h</a>\n</li>\n<li>sp_session_is_scrobbling()\n: <a class=\"el\" href=\"group__session.html#ga6a56bc82ff0b369bb6e0f035534ce33d\">api.h</a>\n</li>\n<li>sp_session_is_scrobbling_possible()\n: <a class=\"el\" href=\"group__session.html#ga0fad03ceabcf8d68af78f0f35fcbcc8d\">api.h</a>\n</li>\n<li>sp_session_login()\n: <a class=\"el\" href=\"group__session.html#ga4533a992a120cacb109c892a852afe2a\">api.h</a>\n</li>\n<li>sp_session_logout()\n: <a class=\"el\" href=\"group__session.html#gab7f08ca0939985b30ae2d1ed9db1d726\">api.h</a>\n</li>\n<li>sp_session_player_load()\n: <a class=\"el\" href=\"group__session.html#gac73bf2c569a43d824439b557d5e4b293\">api.h</a>\n</li>\n<li>sp_session_player_play()\n: <a class=\"el\" href=\"group__session.html#gab66c5915967e4f90db945b118e620624\">api.h</a>\n</li>\n<li>sp_session_player_prefetch()\n: <a class=\"el\" href=\"group__session.html#gaf42e30a1f430ac7c436c7d9f0485368d\">api.h</a>\n</li>\n<li>sp_session_player_seek()\n: <a class=\"el\" href=\"group__session.html#ga3430cd4f11541868d3f83eaa31aecf44\">api.h</a>\n</li>\n<li>sp_session_player_unload()\n: <a class=\"el\" href=\"group__session.html#gafa7ee2803f119451bb8be3bf28746975\">api.h</a>\n</li>\n<li>sp_session_playlistcontainer()\n: <a class=\"el\" href=\"group__session.html#ga319767f0b795f1c46a08390b587c5671\">api.h</a>\n</li>\n<li>sp_session_preferred_bitrate()\n: <a class=\"el\" href=\"group__session.html#gacd590e095b011af42fb10046117846fe\">api.h</a>\n</li>\n<li>sp_session_preferred_offline_bitrate()\n: <a class=\"el\" href=\"group__session.html#ga4bba5f828d6c87692f2c355cc8f07c61\">api.h</a>\n</li>\n<li>sp_session_process_events()\n: <a class=\"el\" href=\"group__session.html#gaff27cb730db6debf55e750e39e7fadd7\">api.h</a>\n</li>\n<li>sp_session_publishedcontainer_for_user_create()\n: <a class=\"el\" href=\"group__session.html#ga4ad3a1de596a41f275120dad3bb4685d\">api.h</a>\n</li>\n<li>sp_session_release()\n: <a class=\"el\" href=\"group__session.html#gab81c540b76f7425a9cc0dbf270c09674\">api.h</a>\n</li>\n<li>sp_session_relogin()\n: <a class=\"el\" href=\"group__session.html#gae1bc9bebd230226c3d48925cd1be6edf\">api.h</a>\n</li>\n<li>sp_session_remembered_user()\n: <a class=\"el\" href=\"group__session.html#gab349c7bfe59e10e167bd75c20df9fc97\">api.h</a>\n</li>\n<li>sp_session_set_cache_size()\n: <a class=\"el\" href=\"group__session.html#ga6f27c55d1ce9f3f794fcce7bee7adfea\">api.h</a>\n</li>\n<li>sp_session_set_connection_rules()\n: <a class=\"el\" href=\"group__session.html#ga0ac85299c37710321b6d64713e1d6ba8\">api.h</a>\n</li>\n<li>sp_session_set_connection_type()\n: <a class=\"el\" href=\"group__session.html#gaf81c61799e0ccdbba048fb79ec050930\">api.h</a>\n</li>\n<li>sp_session_set_private_session()\n: <a class=\"el\" href=\"group__session.html#ga42a8f0999316ac7f141926092879ad2f\">api.h</a>\n</li>\n<li>sp_session_set_scrobbling()\n: <a class=\"el\" href=\"group__session.html#ga2475a1fbc2eeacccb96b7f36efd36725\">api.h</a>\n</li>\n<li>sp_session_set_social_credentials()\n: <a class=\"el\" href=\"group__session.html#ga9e5ee46ef5e75aa462607caac984f2de\">api.h</a>\n</li>\n<li>sp_session_set_volume_normalization()\n: <a class=\"el\" href=\"group__session.html#ga4e14f58356d00e3693be84623bf6bd11\">api.h</a>\n</li>\n<li>sp_session_starred_create()\n: <a class=\"el\" href=\"group__session.html#ga02391c9e28cff0a602f7139542e0238f\">api.h</a>\n</li>\n<li>sp_session_starred_for_user_create()\n: <a class=\"el\" href=\"group__session.html#ga9be806a719a6399bfe1fd0d4c125e0eb\">api.h</a>\n</li>\n<li>sp_session_user()\n: <a class=\"el\" href=\"group__session.html#ga267bbcae24b6bb1fd56de56678a5f455\">api.h</a>\n</li>\n<li>sp_session_user_country()\n: <a class=\"el\" href=\"group__session.html#ga54c7693afa9be664f3ea870feb0df8d9\">api.h</a>\n</li>\n<li>sp_session_user_name()\n: <a class=\"el\" href=\"group__session.html#gac7a365c2166738909cdb901edebc3f70\">api.h</a>\n</li>\n<li>sp_session_userdata()\n: <a class=\"el\" href=\"group__session.html#gabfb3f59b20ae0b225e154eb9095152b2\">api.h</a>\n</li>\n<li>sp_toplistbrowse_add_ref()\n: <a class=\"el\" href=\"group__toplist.html#ga421a19f128e5f3ae4b36e63a133a2a83\">api.h</a>\n</li>\n<li>sp_toplistbrowse_album()\n: <a class=\"el\" href=\"group__toplist.html#gaa080ace445d269f56942ac3d7f1f157e\">api.h</a>\n</li>\n<li>sp_toplistbrowse_artist()\n: <a class=\"el\" href=\"group__toplist.html#ga504cc45074d40c817dffbcc2906ef57f\">api.h</a>\n</li>\n<li>sp_toplistbrowse_backend_request_duration()\n: <a class=\"el\" href=\"group__toplist.html#gab9cf87d6b6a8cbd8d36cd6e94a3270ee\">api.h</a>\n</li>\n<li>sp_toplistbrowse_create()\n: <a class=\"el\" href=\"group__toplist.html#gac2fe366e0050747438e09cdd22ed0e31\">api.h</a>\n</li>\n<li>sp_toplistbrowse_error()\n: <a class=\"el\" href=\"group__toplist.html#ga9b881929e74d97f64814ae54953ce4d7\">api.h</a>\n</li>\n<li>sp_toplistbrowse_is_loaded()\n: <a class=\"el\" href=\"group__toplist.html#gaff81156c09d311c4f6a82d28a32d7968\">api.h</a>\n</li>\n<li>sp_toplistbrowse_num_albums()\n: <a class=\"el\" href=\"group__toplist.html#ga69f5e70269c1eb08e1ddb1c77bb8c3e3\">api.h</a>\n</li>\n<li>sp_toplistbrowse_num_artists()\n: <a class=\"el\" href=\"group__toplist.html#gae2f5c09fbbf947834b1b1e73461f1fb3\">api.h</a>\n</li>\n<li>sp_toplistbrowse_num_tracks()\n: <a class=\"el\" href=\"group__toplist.html#gaeb0ddfd565474dc7e444aabebbc119b7\">api.h</a>\n</li>\n<li>sp_toplistbrowse_release()\n: <a class=\"el\" href=\"group__toplist.html#gac6cf969c9cb6b431aeaa4723820ca8de\">api.h</a>\n</li>\n<li>sp_toplistbrowse_track()\n: <a class=\"el\" href=\"group__toplist.html#gaf3d00b8bf089134a4f320a8d3d6ab683\">api.h</a>\n</li>\n<li>sp_track_add_ref()\n: <a class=\"el\" href=\"group__track.html#ga7d86041a2bf75590f55978521c08e38c\">api.h</a>\n</li>\n<li>sp_track_album()\n: <a class=\"el\" href=\"group__track.html#ga39a0f52244472cb2d450ea9ba6807304\">api.h</a>\n</li>\n<li>sp_track_artist()\n: <a class=\"el\" href=\"group__track.html#ga67cd0c035627a1e4a54642213fdf1d75\">api.h</a>\n</li>\n<li>sp_track_disc()\n: <a class=\"el\" href=\"group__track.html#ga9d464ee4a5c8836b59888952b960223a\">api.h</a>\n</li>\n<li>sp_track_duration()\n: <a class=\"el\" href=\"group__track.html#gac817937bd8d8355b6a1949b76d0b5560\">api.h</a>\n</li>\n<li>sp_track_error()\n: <a class=\"el\" href=\"group__track.html#ga947c0f7755b0c4955ca0b0993db0f2b5\">api.h</a>\n</li>\n<li>sp_track_get_availability()\n: <a class=\"el\" href=\"group__track.html#ga9c78846badae6567fe9f9a3792fd06c8\">api.h</a>\n</li>\n<li>sp_track_get_playable()\n: <a class=\"el\" href=\"group__track.html#ga112dca47d0bac39818b55119ef134ffd\">api.h</a>\n</li>\n<li>sp_track_index()\n: <a class=\"el\" href=\"group__track.html#ga25c1df9d32fd58f243397740b29c3f61\">api.h</a>\n</li>\n<li>sp_track_is_autolinked()\n: <a class=\"el\" href=\"group__track.html#ga4eeb86de13187697cd9dfe0b0934988d\">api.h</a>\n</li>\n<li>sp_track_is_loaded()\n: <a class=\"el\" href=\"group__track.html#ga8b69cf193679c7e00031ae43e61c6a54\">api.h</a>\n</li>\n<li>sp_track_is_local()\n: <a class=\"el\" href=\"group__track.html#gabcb75da69e0338006bdbd2f2f467f082\">api.h</a>\n</li>\n<li>sp_track_is_placeholder()\n: <a class=\"el\" href=\"group__track.html#ga2367d906c578e674d0d470d8c1ee3b33\">api.h</a>\n</li>\n<li>sp_track_is_starred()\n: <a class=\"el\" href=\"group__track.html#gab17d380ac941e102af0f308ad885b3c3\">api.h</a>\n</li>\n<li>sp_track_name()\n: <a class=\"el\" href=\"group__track.html#ga8eb423d3cc2cbfb743c7f23ffb8d0fad\">api.h</a>\n</li>\n<li>sp_track_num_artists()\n: <a class=\"el\" href=\"group__track.html#ga0aa945fc43e35d36cc334a52735d83b2\">api.h</a>\n</li>\n<li>sp_track_offline_get_status()\n: <a class=\"el\" href=\"group__track.html#ga281e0ad4373579c5d24202ea1f93fe7b\">api.h</a>\n</li>\n<li>sp_track_popularity()\n: <a class=\"el\" href=\"group__track.html#ga4570f08f968edbff519b44d2241d2255\">api.h</a>\n</li>\n<li>sp_track_release()\n: <a class=\"el\" href=\"group__track.html#gaa11098d82e6c2ae42fc2ea1486e741de\">api.h</a>\n</li>\n<li>sp_track_set_starred()\n: <a class=\"el\" href=\"group__track.html#ga34b5a712fb2c683402ff78df73e7545c\">api.h</a>\n</li>\n<li>sp_user_add_ref()\n: <a class=\"el\" href=\"group__user.html#ga232816a3c8f42ef2663b8d99261f2dae\">api.h</a>\n</li>\n<li>sp_user_canonical_name()\n: <a class=\"el\" href=\"group__user.html#gad9ac5456cd129c31d2c577ba14e88f8c\">api.h</a>\n</li>\n<li>sp_user_display_name()\n: <a class=\"el\" href=\"group__user.html#ga0052befb81a93bb7106ca863de892610\">api.h</a>\n</li>\n<li>sp_user_is_loaded()\n: <a class=\"el\" href=\"group__user.html#ga0996fb9814564e4ad39b8a500cb3de21\">api.h</a>\n</li>\n<li>sp_user_release()\n: <a class=\"el\" href=\"group__user.html#gab1ffba4355073e1f72594c9e1b22ebb4\">api.h</a>\n</li>\n</ul>\n</div>\n<hr size=\"1\"><address style=\"text-align: right;\"><small>\nGenerated on Wed Jun 13 2012 14:22:40.<br>\nCopyright &copy; 2006&ndash;2012 Spotify Ltd</small></address>\n</body>\n</html>\n"
  },
  {
    "path": "libspotify/docs/html/globals_type.html",
    "content": "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\n<html xmlns=\"http://www.w3.org/1999/xhtml\">\n<head>\n<meta http-equiv=\"Content-Type\" content=\"text/xhtml;charset=UTF-8\"/>\n<title>libspotify: Data Fields</title>\n<link href=\"tabs.css\" rel=\"stylesheet\" type=\"text/css\"/>\n<link href=\"doxygen.css\" rel=\"stylesheet\" type=\"text/css\"/>\n</head>\n<body>\n<!-- Generated by Doxygen 1.7.1 -->\n<div class=\"navigation\" id=\"top\">\n  <div class=\"tabs\">\n    <ul class=\"tablist\">\n      <li><a href=\"index.html\"><span>Main&nbsp;Page</span></a></li>\n      <li><a href=\"modules.html\"><span>Modules</span></a></li>\n      <li><a href=\"annotated.html\"><span>Data&nbsp;Structures</span></a></li>\n      <li class=\"current\"><a href=\"files.html\"><span>Files</span></a></li>\n      <li><a href=\"examples.html\"><span>Examples</span></a></li>\n    </ul>\n  </div>\n  <div class=\"tabs2\">\n    <ul class=\"tablist\">\n      <li><a href=\"files.html\"><span>File&nbsp;List</span></a></li>\n      <li class=\"current\"><a href=\"globals.html\"><span>Globals</span></a></li>\n    </ul>\n  </div>\n  <div class=\"tabs2\">\n    <ul class=\"tablist\">\n      <li><a href=\"globals.html\"><span>All</span></a></li>\n      <li><a href=\"globals_func.html\"><span>Functions</span></a></li>\n      <li class=\"current\"><a href=\"globals_type.html\"><span>Typedefs</span></a></li>\n      <li><a href=\"globals_enum.html\"><span>Enumerations</span></a></li>\n      <li><a href=\"globals_eval.html\"><span>Enumerator</span></a></li>\n      <li><a href=\"globals_defs.html\"><span>Defines</span></a></li>\n    </ul>\n  </div>\n  <div class=\"tabs3\">\n    <ul class=\"tablist\">\n      <li><a href=\"#index_a\"><span>a</span></a></li>\n      <li><a href=\"#index_i\"><span>i</span></a></li>\n      <li><a href=\"#index_s\"><span>s</span></a></li>\n      <li><a href=\"#index_t\"><span>t</span></a></li>\n    </ul>\n  </div>\n</div>\n<div class=\"contents\">\n&nbsp;\n\n<h3><a class=\"anchor\" id=\"index_a\"></a>- a -</h3><ul>\n<li>albumbrowse_complete_cb\n: <a class=\"el\" href=\"group__albumbrowse.html#gabd76254f89048e6d368929015a0c739f\">api.h</a>\n</li>\n<li>artistbrowse_complete_cb\n: <a class=\"el\" href=\"group__artistbrowse.html#ga8077aa18c043210e859479be2616a3e7\">api.h</a>\n</li>\n</ul>\n\n\n<h3><a class=\"anchor\" id=\"index_i\"></a>- i -</h3><ul>\n<li>image_loaded_cb\n: <a class=\"el\" href=\"group__image.html#ga713bef7c5dedba7d91b9710cd9b5faa4\">api.h</a>\n</li>\n<li>inboxpost_complete_cb\n: <a class=\"el\" href=\"group__inbox.html#ga5084d6ab753294730402a0c43b82e60c\">api.h</a>\n</li>\n</ul>\n\n\n<h3><a class=\"anchor\" id=\"index_s\"></a>- s -</h3><ul>\n<li>search_complete_cb\n: <a class=\"el\" href=\"group__search.html#gabcd51c99a318b9f36dfe2948d8209bb1\">api.h</a>\n</li>\n<li>sp_album\n: <a class=\"el\" href=\"group__types.html#ga6fd3e5de729c429fef3ff18ece6dcfad\">api.h</a>\n</li>\n<li>sp_albumbrowse\n: <a class=\"el\" href=\"group__types.html#ga9c4550473a7a07790778ba870c31b4d9\">api.h</a>\n</li>\n<li>sp_artist\n: <a class=\"el\" href=\"group__types.html#ga31764fbd69618c10be173c6c03d4c1bc\">api.h</a>\n</li>\n<li>sp_artistbrowse\n: <a class=\"el\" href=\"group__types.html#gafd3d5aae485f1012ec91b7948e6f9f2b\">api.h</a>\n</li>\n<li>sp_artistbrowse_type\n: <a class=\"el\" href=\"group__session.html#gab947eba77c176504c69cbb2f1de9830d\">api.h</a>\n</li>\n<li>sp_audio_buffer_stats\n: <a class=\"el\" href=\"group__session.html#ga25462859a596a247ba5cc1853fc32cca\">api.h</a>\n</li>\n<li>sp_audioformat\n: <a class=\"el\" href=\"group__session.html#ga5338d4a10576ba8d6ab11b70892d503c\">api.h</a>\n</li>\n<li>sp_bitrate\n: <a class=\"el\" href=\"group__session.html#ga83d3de45241a44e787410993c5fac0ea\">api.h</a>\n</li>\n<li>sp_connection_rules\n: <a class=\"el\" href=\"group__session.html#ga24ee483cdceef9af3b415c020b197a75\">api.h</a>\n</li>\n<li>sp_connection_type\n: <a class=\"el\" href=\"group__session.html#ga05a7dbb946a9c47bf011f3f3d77964c3\">api.h</a>\n</li>\n<li>sp_connectionstate\n: <a class=\"el\" href=\"group__session.html#gac0fa3d4cc60bd2e3d666026f88980e8c\">api.h</a>\n</li>\n<li>sp_error\n: <a class=\"el\" href=\"group__error.html#ga83154178d3a32668658734d2facfa22b\">api.h</a>\n</li>\n<li>sp_image\n: <a class=\"el\" href=\"group__types.html#ga61155ca7b1ba941e15490e417441917b\">api.h</a>\n</li>\n<li>sp_image_size\n: <a class=\"el\" href=\"group__session.html#gaca320fd41bd0556b7fa1f2fa6e14faee\">api.h</a>\n</li>\n<li>sp_inbox\n: <a class=\"el\" href=\"group__types.html#gaec0f2e5098cebc05ce56adfc9b346510\">api.h</a>\n</li>\n<li>sp_link\n: <a class=\"el\" href=\"group__types.html#gaf90a23d6b662c96d52ac19f7f4bc1e39\">api.h</a>\n</li>\n<li>sp_offline_sync_status\n: <a class=\"el\" href=\"group__session.html#gaa7f24f13d6d105869c405045a4cc2a20\">api.h</a>\n</li>\n<li>sp_playlist\n: <a class=\"el\" href=\"group__types.html#ga1bcf54cbc117a20ab2c15e59eb3a8174\">api.h</a>\n</li>\n<li>sp_playlist_callbacks\n: <a class=\"el\" href=\"group__playlist.html#ga8249fe3d53c6dce0f154d0bfd3e80c6a\">api.h</a>\n</li>\n<li>sp_playlist_offline_status\n: <a class=\"el\" href=\"group__session.html#gac507efa32e8c122fbe9ea41d96180d06\">api.h</a>\n</li>\n<li>sp_playlist_type\n: <a class=\"el\" href=\"group__session.html#ga86723f553db2db6a8f507cd748948ad4\">api.h</a>\n</li>\n<li>sp_playlistcontainer\n: <a class=\"el\" href=\"group__types.html#ga45a2febbe167483e48dab8d606d462d7\">api.h</a>\n</li>\n<li>sp_playlistcontainer_callbacks\n: <a class=\"el\" href=\"group__playlist.html#ga8786e3840bb3774fc929183e3a9df281\">api.h</a>\n</li>\n<li>sp_relation_type\n: <a class=\"el\" href=\"group__user.html#ga3a5dbf9aee629d8a9b43dfb24881a9b4\">api.h</a>\n</li>\n<li>sp_sampletype\n: <a class=\"el\" href=\"group__session.html#ga5ef462e78d5a5af60dd0e7085b1ba512\">api.h</a>\n</li>\n<li>sp_search\n: <a class=\"el\" href=\"group__types.html#gac95893a6b23d4b19f6f149eed6ead1fd\">api.h</a>\n</li>\n<li>sp_search_type\n: <a class=\"el\" href=\"group__session.html#ga647e4de81e5ac0a2e5d1193b1005ed3e\">api.h</a>\n</li>\n<li>sp_session\n: <a class=\"el\" href=\"group__types.html#ga70dd19c6f824cf6a159575aa4c128b53\">api.h</a>\n</li>\n<li>sp_session_callbacks\n: <a class=\"el\" href=\"group__session.html#gaf1d92302cd5d0d4a032e1408188c8fd5\">api.h</a>\n</li>\n<li>sp_session_config\n: <a class=\"el\" href=\"group__session.html#ga372b25a93da38d4d707b0c2eaa7b3ebb\">api.h</a>\n</li>\n<li>sp_subscribers\n: <a class=\"el\" href=\"group__session.html#gafb515e30d134c61b8eaaff3177af0b5b\">api.h</a>\n</li>\n<li>sp_toplistbrowse\n: <a class=\"el\" href=\"group__types.html#ga723de429cd073bcf5d13fb4e0f466ffd\">api.h</a>\n</li>\n<li>sp_track\n: <a class=\"el\" href=\"group__types.html#ga47bbd2262f0c8b5d7147af7d62198e48\">api.h</a>\n</li>\n<li>sp_track_availability\n: <a class=\"el\" href=\"group__session.html#ga60c7ff53ddbc04c036a23181b7275d69\">api.h</a>\n</li>\n<li>sp_track_offline_status\n: <a class=\"el\" href=\"group__session.html#gae689044941537050de641a1dcd4c75d5\">api.h</a>\n</li>\n<li>sp_user\n: <a class=\"el\" href=\"group__types.html#gaed2dbaa1eebd6752f76613daad9158bc\">api.h</a>\n</li>\n</ul>\n\n\n<h3><a class=\"anchor\" id=\"index_t\"></a>- t -</h3><ul>\n<li>toplistbrowse_complete_cb\n: <a class=\"el\" href=\"group__toplist.html#gafe8e94ae23133105f35c03b9e3836a0a\">api.h</a>\n</li>\n</ul>\n</div>\n<hr size=\"1\"><address style=\"text-align: right;\"><small>\nGenerated on Wed Jun 13 2012 14:22:40.<br>\nCopyright &copy; 2006&ndash;2012 Spotify Ltd</small></address>\n</body>\n</html>\n"
  },
  {
    "path": "libspotify/docs/html/group__album.html",
    "content": "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\n<html xmlns=\"http://www.w3.org/1999/xhtml\">\n<head>\n<meta http-equiv=\"Content-Type\" content=\"text/xhtml;charset=UTF-8\"/>\n<title>libspotify: Album subsystem</title>\n<link href=\"tabs.css\" rel=\"stylesheet\" type=\"text/css\"/>\n<link href=\"doxygen.css\" rel=\"stylesheet\" type=\"text/css\"/>\n</head>\n<body>\n<!-- Generated by Doxygen 1.7.1 -->\n<div class=\"navigation\" id=\"top\">\n  <div class=\"tabs\">\n    <ul class=\"tablist\">\n      <li><a href=\"index.html\"><span>Main&nbsp;Page</span></a></li>\n      <li><a href=\"modules.html\"><span>Modules</span></a></li>\n      <li><a href=\"annotated.html\"><span>Data&nbsp;Structures</span></a></li>\n      <li><a href=\"files.html\"><span>Files</span></a></li>\n      <li><a href=\"examples.html\"><span>Examples</span></a></li>\n    </ul>\n  </div>\n</div>\n<div class=\"header\">\n  <div class=\"summary\">\n<a href=\"#enum-members\">Enumerations</a> &#124;\n<a href=\"#func-members\">Functions</a>  </div>\n  <div class=\"headertitle\">\n<h1>Album subsystem</h1>  </div>\n</div>\n<div class=\"contents\">\n<table class=\"memberdecls\">\n<tr><td colspan=\"2\"><h2><a name=\"enum-members\"></a>\nEnumerations</h2></td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">enum &nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__album.html#ga019b49a9d1633b61daa79c80ea01d5c3\">sp_albumtype</a> { <br/>\n&nbsp;&nbsp;<a class=\"el\" href=\"group__album.html#gga019b49a9d1633b61daa79c80ea01d5c3ad1693d93a2c05c053fc4fd77886af8dd\">SP_ALBUMTYPE_ALBUM</a> =  0, \n<br/>\n&nbsp;&nbsp;<a class=\"el\" href=\"group__album.html#gga019b49a9d1633b61daa79c80ea01d5c3a3b6f78b733f1bc18a5e4fa18c020fc73\">SP_ALBUMTYPE_SINGLE</a> =  1, \n<br/>\n&nbsp;&nbsp;<a class=\"el\" href=\"group__album.html#gga019b49a9d1633b61daa79c80ea01d5c3a8fee6ba46e8876037f4f2e46c6d6c6af\">SP_ALBUMTYPE_COMPILATION</a> =  2, \n<br/>\n&nbsp;&nbsp;<a class=\"el\" href=\"group__album.html#gga019b49a9d1633b61daa79c80ea01d5c3ad564ed5f1f0659929fe5ec700513873f\">SP_ALBUMTYPE_UNKNOWN</a> =  3\n<br/>\n }</td></tr>\n<tr><td colspan=\"2\"><h2><a name=\"func-members\"></a>\nFunctions</h2></td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">bool&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__album.html#ga46fbfa98be12c2f4067d5e679552cfb9\">sp_album_is_loaded</a> (<a class=\"el\" href=\"group__types.html#ga6fd3e5de729c429fef3ff18ece6dcfad\">sp_album</a> *album)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">bool&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__album.html#ga89eb8dc73a76f5e0509b1066426495f7\">sp_album_is_available</a> (<a class=\"el\" href=\"group__types.html#ga6fd3e5de729c429fef3ff18ece6dcfad\">sp_album</a> *album)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__types.html#ga31764fbd69618c10be173c6c03d4c1bc\">sp_artist</a> *&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__album.html#ga42309972141dab10c32d741d357c01de\">sp_album_artist</a> (<a class=\"el\" href=\"group__types.html#ga6fd3e5de729c429fef3ff18ece6dcfad\">sp_album</a> *album)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">const byte *&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__album.html#ga6616ef3df724af185c5eb58e8a0fb808\">sp_album_cover</a> (<a class=\"el\" href=\"group__types.html#ga6fd3e5de729c429fef3ff18ece6dcfad\">sp_album</a> *album, <a class=\"el\" href=\"group__session.html#ga61bc424465d776af3ceeb69eee2bb492\">sp_image_size</a> size)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">const char *&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__album.html#ga0e828c991a8184d60026513f944e19ad\">sp_album_name</a> (<a class=\"el\" href=\"group__types.html#ga6fd3e5de729c429fef3ff18ece6dcfad\">sp_album</a> *album)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">int&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__album.html#ga2aadf934b0af43c3ef6ee98b6a8065fd\">sp_album_year</a> (<a class=\"el\" href=\"group__types.html#ga6fd3e5de729c429fef3ff18ece6dcfad\">sp_album</a> *album)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__album.html#ga019b49a9d1633b61daa79c80ea01d5c3\">sp_albumtype</a>&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__album.html#ga8dceb04a62bdb3ffc112ed0efc359e51\">sp_album_type</a> (<a class=\"el\" href=\"group__types.html#ga6fd3e5de729c429fef3ff18ece6dcfad\">sp_album</a> *album)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__error.html#gafd27986ce4cd9eeaeca8adda83c9eb6b\">sp_error</a>&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__album.html#ga08192dd38d1c628f7b51615fffa33017\">sp_album_add_ref</a> (<a class=\"el\" href=\"group__types.html#ga6fd3e5de729c429fef3ff18ece6dcfad\">sp_album</a> *album)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__error.html#gafd27986ce4cd9eeaeca8adda83c9eb6b\">sp_error</a>&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__album.html#ga5c6e49d04ffb05c722db5e78c9434b88\">sp_album_release</a> (<a class=\"el\" href=\"group__types.html#ga6fd3e5de729c429fef3ff18ece6dcfad\">sp_album</a> *album)</td></tr>\n</table>\n<hr/><h2>Enumeration Type Documentation</h2>\n<a class=\"anchor\" id=\"ga019b49a9d1633b61daa79c80ea01d5c3\"></a><!-- doxytag: member=\"api.h::sp_albumtype\" ref=\"ga019b49a9d1633b61daa79c80ea01d5c3\" args=\"\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\">enum <a class=\"el\" href=\"group__album.html#ga019b49a9d1633b61daa79c80ea01d5c3\">sp_albumtype</a></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Album types </p>\n<dl><dt><b>Enumerator: </b></dt><dd><table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n<tr><td valign=\"top\"><em><a class=\"anchor\" id=\"gga019b49a9d1633b61daa79c80ea01d5c3ad1693d93a2c05c053fc4fd77886af8dd\"></a><!-- doxytag: member=\"SP_ALBUMTYPE_ALBUM\" ref=\"gga019b49a9d1633b61daa79c80ea01d5c3ad1693d93a2c05c053fc4fd77886af8dd\" args=\"\" -->SP_ALBUMTYPE_ALBUM</em>&nbsp;</td><td>\n<p>Normal album. </p>\n</td></tr>\n<tr><td valign=\"top\"><em><a class=\"anchor\" id=\"gga019b49a9d1633b61daa79c80ea01d5c3a3b6f78b733f1bc18a5e4fa18c020fc73\"></a><!-- doxytag: member=\"SP_ALBUMTYPE_SINGLE\" ref=\"gga019b49a9d1633b61daa79c80ea01d5c3a3b6f78b733f1bc18a5e4fa18c020fc73\" args=\"\" -->SP_ALBUMTYPE_SINGLE</em>&nbsp;</td><td>\n<p>Single. </p>\n</td></tr>\n<tr><td valign=\"top\"><em><a class=\"anchor\" id=\"gga019b49a9d1633b61daa79c80ea01d5c3a8fee6ba46e8876037f4f2e46c6d6c6af\"></a><!-- doxytag: member=\"SP_ALBUMTYPE_COMPILATION\" ref=\"gga019b49a9d1633b61daa79c80ea01d5c3a8fee6ba46e8876037f4f2e46c6d6c6af\" args=\"\" -->SP_ALBUMTYPE_COMPILATION</em>&nbsp;</td><td>\n<p>Compilation. </p>\n</td></tr>\n<tr><td valign=\"top\"><em><a class=\"anchor\" id=\"gga019b49a9d1633b61daa79c80ea01d5c3ad564ed5f1f0659929fe5ec700513873f\"></a><!-- doxytag: member=\"SP_ALBUMTYPE_UNKNOWN\" ref=\"gga019b49a9d1633b61daa79c80ea01d5c3ad564ed5f1f0659929fe5ec700513873f\" args=\"\" -->SP_ALBUMTYPE_UNKNOWN</em>&nbsp;</td><td>\n<p>Unknown type. </p>\n</td></tr>\n</table>\n</dd>\n</dl>\n\n</div>\n</div>\n<hr/><h2>Function Documentation</h2>\n<a class=\"anchor\" id=\"ga08192dd38d1c628f7b51615fffa33017\"></a><!-- doxytag: member=\"api.h::sp_album_add_ref\" ref=\"ga08192dd38d1c628f7b51615fffa33017\" args=\"(sp_album *album)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\"><a class=\"el\" href=\"group__error.html#gafd27986ce4cd9eeaeca8adda83c9eb6b\">sp_error</a> sp_album_add_ref </td>\n          <td>(</td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__types.html#ga6fd3e5de729c429fef3ff18ece6dcfad\">sp_album</a> *&nbsp;</td>\n          <td class=\"paramname\"> <em>album</em></td>\n          <td>&nbsp;)&nbsp;</td>\n          <td></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Increase the reference count of an album</p>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>album</em>&nbsp;</td><td>The album object </td></tr>\n  </table>\n  </dd>\n</dl>\n<dl class=\"return\"><dt><b>Returns:</b></dt><dd>One of the following errors, from <a class=\"el\" href=\"group__error.html#ga83154178d3a32668658734d2facfa22b\">sp_error</a> SP_ERROR_OK </dd></dl>\n\n</div>\n</div>\n<a class=\"anchor\" id=\"ga42309972141dab10c32d741d357c01de\"></a><!-- doxytag: member=\"api.h::sp_album_artist\" ref=\"ga42309972141dab10c32d741d357c01de\" args=\"(sp_album *album)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\"><a class=\"el\" href=\"group__types.html#ga31764fbd69618c10be173c6c03d4c1bc\">sp_artist</a>* sp_album_artist </td>\n          <td>(</td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__types.html#ga6fd3e5de729c429fef3ff18ece6dcfad\">sp_album</a> *&nbsp;</td>\n          <td class=\"paramname\"> <em>album</em></td>\n          <td>&nbsp;)&nbsp;</td>\n          <td></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Get the artist associated with the given album</p>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>album</em>&nbsp;</td><td>Album object </td></tr>\n  </table>\n  </dd>\n</dl>\n<dl class=\"return\"><dt><b>Returns:</b></dt><dd>A reference to the artist. NULL if the metadata has not been loaded yet </dd></dl>\n<dl><dt><b>Examples: </b></dt><dd><a class=\"el\" href=\"toplist_8c-example.html#a2\">toplist.c</a>.</dd>\n</dl>\n</div>\n</div>\n<a class=\"anchor\" id=\"ga6616ef3df724af185c5eb58e8a0fb808\"></a><!-- doxytag: member=\"api.h::sp_album_cover\" ref=\"ga6616ef3df724af185c5eb58e8a0fb808\" args=\"(sp_album *album, sp_image_size size)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\">const byte* sp_album_cover </td>\n          <td>(</td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__types.html#ga6fd3e5de729c429fef3ff18ece6dcfad\">sp_album</a> *&nbsp;</td>\n          <td class=\"paramname\"> <em>album</em>, </td>\n        </tr>\n        <tr>\n          <td class=\"paramkey\"></td>\n          <td></td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__session.html#ga61bc424465d776af3ceeb69eee2bb492\">sp_image_size</a>&nbsp;</td>\n          <td class=\"paramname\"> <em>size</em></td><td>&nbsp;</td>\n        </tr>\n        <tr>\n          <td></td>\n          <td>)</td>\n          <td></td><td></td><td></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Return image ID representing the album's coverart.</p>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>album</em>&nbsp;</td><td>Album object </td></tr>\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>size</em>&nbsp;</td><td>The desired size of the image</td></tr>\n  </table>\n  </dd>\n</dl>\n<dl class=\"return\"><dt><b>Returns:</b></dt><dd>ID byte sequence that can be passed to <a class=\"el\" href=\"group__image.html#gaf29e89f45945db2b3667bf9db4279c33\">sp_image_create()</a> If the album has no image or the metadata for the album is not loaded yet, this function returns NULL.</dd></dl>\n<dl class=\"see\"><dt><b>See also:</b></dt><dd><a class=\"el\" href=\"group__image.html#gaf29e89f45945db2b3667bf9db4279c33\">sp_image_create</a> </dd></dl>\n\n</div>\n</div>\n<a class=\"anchor\" id=\"ga89eb8dc73a76f5e0509b1066426495f7\"></a><!-- doxytag: member=\"api.h::sp_album_is_available\" ref=\"ga89eb8dc73a76f5e0509b1066426495f7\" args=\"(sp_album *album)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\">bool sp_album_is_available </td>\n          <td>(</td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__types.html#ga6fd3e5de729c429fef3ff18ece6dcfad\">sp_album</a> *&nbsp;</td>\n          <td class=\"paramname\"> <em>album</em></td>\n          <td>&nbsp;)&nbsp;</td>\n          <td></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Return true if the album is available in the current region.</p>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>album</em>&nbsp;</td><td>The album</td></tr>\n  </table>\n  </dd>\n</dl>\n<dl class=\"return\"><dt><b>Returns:</b></dt><dd>True if album is available for playback, otherwise false.</dd></dl>\n<dl class=\"note\"><dt><b>Note:</b></dt><dd>The album must be loaded or this function will always return false. </dd></dl>\n<dl class=\"see\"><dt><b>See also:</b></dt><dd><a class=\"el\" href=\"group__album.html#ga46fbfa98be12c2f4067d5e679552cfb9\">sp_album_is_loaded()</a> </dd></dl>\n\n</div>\n</div>\n<a class=\"anchor\" id=\"ga46fbfa98be12c2f4067d5e679552cfb9\"></a><!-- doxytag: member=\"api.h::sp_album_is_loaded\" ref=\"ga46fbfa98be12c2f4067d5e679552cfb9\" args=\"(sp_album *album)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\">bool sp_album_is_loaded </td>\n          <td>(</td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__types.html#ga6fd3e5de729c429fef3ff18ece6dcfad\">sp_album</a> *&nbsp;</td>\n          <td class=\"paramname\"> <em>album</em></td>\n          <td>&nbsp;)&nbsp;</td>\n          <td></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Check if the album object is populated with data</p>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>album</em>&nbsp;</td><td>Album object </td></tr>\n  </table>\n  </dd>\n</dl>\n<dl class=\"return\"><dt><b>Returns:</b></dt><dd>True if metadata is present, false if not </dd></dl>\n\n</div>\n</div>\n<a class=\"anchor\" id=\"ga0e828c991a8184d60026513f944e19ad\"></a><!-- doxytag: member=\"api.h::sp_album_name\" ref=\"ga0e828c991a8184d60026513f944e19ad\" args=\"(sp_album *album)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\">const char* sp_album_name </td>\n          <td>(</td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__types.html#ga6fd3e5de729c429fef3ff18ece6dcfad\">sp_album</a> *&nbsp;</td>\n          <td class=\"paramname\"> <em>album</em></td>\n          <td>&nbsp;)&nbsp;</td>\n          <td></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Return name of album</p>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>album</em>&nbsp;</td><td>Album object</td></tr>\n  </table>\n  </dd>\n</dl>\n<dl class=\"return\"><dt><b>Returns:</b></dt><dd>Name of album. Returned string is valid as long as the album object stays allocated and no longer than the next call to <a class=\"el\" href=\"group__session.html#gaff27cb730db6debf55e750e39e7fadd7\">sp_session_process_events()</a> </dd></dl>\n<dl><dt><b>Examples: </b></dt><dd><a class=\"el\" href=\"browse_8c-example.html#a13\">browse.c</a>, <a class=\"el\" href=\"search_8c-example.html#a0\">search.c</a>, and <a class=\"el\" href=\"toplist_8c-example.html#a0\">toplist.c</a>.</dd>\n</dl>\n</div>\n</div>\n<a class=\"anchor\" id=\"ga5c6e49d04ffb05c722db5e78c9434b88\"></a><!-- doxytag: member=\"api.h::sp_album_release\" ref=\"ga5c6e49d04ffb05c722db5e78c9434b88\" args=\"(sp_album *album)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\"><a class=\"el\" href=\"group__error.html#gafd27986ce4cd9eeaeca8adda83c9eb6b\">sp_error</a> sp_album_release </td>\n          <td>(</td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__types.html#ga6fd3e5de729c429fef3ff18ece6dcfad\">sp_album</a> *&nbsp;</td>\n          <td class=\"paramname\"> <em>album</em></td>\n          <td>&nbsp;)&nbsp;</td>\n          <td></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Decrease the reference count of an album</p>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>album</em>&nbsp;</td><td>The album object </td></tr>\n  </table>\n  </dd>\n</dl>\n<dl class=\"return\"><dt><b>Returns:</b></dt><dd>One of the following errors, from <a class=\"el\" href=\"group__error.html#ga83154178d3a32668658734d2facfa22b\">sp_error</a> SP_ERROR_OK </dd></dl>\n\n</div>\n</div>\n<a class=\"anchor\" id=\"ga8dceb04a62bdb3ffc112ed0efc359e51\"></a><!-- doxytag: member=\"api.h::sp_album_type\" ref=\"ga8dceb04a62bdb3ffc112ed0efc359e51\" args=\"(sp_album *album)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\"><a class=\"el\" href=\"group__album.html#ga019b49a9d1633b61daa79c80ea01d5c3\">sp_albumtype</a> sp_album_type </td>\n          <td>(</td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__types.html#ga6fd3e5de729c429fef3ff18ece6dcfad\">sp_album</a> *&nbsp;</td>\n          <td class=\"paramname\"> <em>album</em></td>\n          <td>&nbsp;)&nbsp;</td>\n          <td></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Return type of specified album</p>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>album</em>&nbsp;</td><td>Album object</td></tr>\n  </table>\n  </dd>\n</dl>\n<dl class=\"return\"><dt><b>Returns:</b></dt><dd>sp_albumtype </dd></dl>\n\n</div>\n</div>\n<a class=\"anchor\" id=\"ga2aadf934b0af43c3ef6ee98b6a8065fd\"></a><!-- doxytag: member=\"api.h::sp_album_year\" ref=\"ga2aadf934b0af43c3ef6ee98b6a8065fd\" args=\"(sp_album *album)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\">int sp_album_year </td>\n          <td>(</td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__types.html#ga6fd3e5de729c429fef3ff18ece6dcfad\">sp_album</a> *&nbsp;</td>\n          <td class=\"paramname\"> <em>album</em></td>\n          <td>&nbsp;)&nbsp;</td>\n          <td></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Return release year of specified album</p>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>album</em>&nbsp;</td><td>Album object</td></tr>\n  </table>\n  </dd>\n</dl>\n<dl class=\"return\"><dt><b>Returns:</b></dt><dd>Release year </dd></dl>\n<dl><dt><b>Examples: </b></dt><dd><a class=\"el\" href=\"browse_8c-example.html#a15\">browse.c</a>, and <a class=\"el\" href=\"search_8c-example.html#a1\">search.c</a>.</dd>\n</dl>\n</div>\n</div>\n</div>\n<hr size=\"1\"><address style=\"text-align: right;\"><small>\nGenerated on Wed Jun 13 2012 14:22:40.<br>\nCopyright &copy; 2006&ndash;2012 Spotify Ltd</small></address>\n</body>\n</html>\n"
  },
  {
    "path": "libspotify/docs/html/group__albumbrowse.html",
    "content": "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\n<html xmlns=\"http://www.w3.org/1999/xhtml\">\n<head>\n<meta http-equiv=\"Content-Type\" content=\"text/xhtml;charset=UTF-8\"/>\n<title>libspotify: Album browsing</title>\n<link href=\"tabs.css\" rel=\"stylesheet\" type=\"text/css\"/>\n<link href=\"doxygen.css\" rel=\"stylesheet\" type=\"text/css\"/>\n</head>\n<body>\n<!-- Generated by Doxygen 1.7.1 -->\n<div class=\"navigation\" id=\"top\">\n  <div class=\"tabs\">\n    <ul class=\"tablist\">\n      <li><a href=\"index.html\"><span>Main&nbsp;Page</span></a></li>\n      <li><a href=\"modules.html\"><span>Modules</span></a></li>\n      <li><a href=\"annotated.html\"><span>Data&nbsp;Structures</span></a></li>\n      <li><a href=\"files.html\"><span>Files</span></a></li>\n      <li><a href=\"examples.html\"><span>Examples</span></a></li>\n    </ul>\n  </div>\n</div>\n<div class=\"header\">\n  <div class=\"summary\">\n<a href=\"#typedef-members\">Typedefs</a> &#124;\n<a href=\"#func-members\">Functions</a>  </div>\n  <div class=\"headertitle\">\n<h1>Album browsing</h1>  </div>\n</div>\n<div class=\"contents\">\n<table class=\"memberdecls\">\n<tr><td colspan=\"2\"><h2><a name=\"typedef-members\"></a>\nTypedefs</h2></td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">typedef void&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__albumbrowse.html#gabd76254f89048e6d368929015a0c739f\">albumbrowse_complete_cb</a> (<a class=\"el\" href=\"group__types.html#ga9c4550473a7a07790778ba870c31b4d9\">sp_albumbrowse</a> *result, void *userdata)</td></tr>\n<tr><td colspan=\"2\"><h2><a name=\"func-members\"></a>\nFunctions</h2></td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__types.html#ga9c4550473a7a07790778ba870c31b4d9\">sp_albumbrowse</a> *&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__albumbrowse.html#gaf1bc3042e748efea5ca7ac159e5cbfbe\">sp_albumbrowse_create</a> (<a class=\"el\" href=\"group__types.html#ga70dd19c6f824cf6a159575aa4c128b53\">sp_session</a> *session, <a class=\"el\" href=\"group__types.html#ga6fd3e5de729c429fef3ff18ece6dcfad\">sp_album</a> *album, <a class=\"el\" href=\"group__albumbrowse.html#gabd76254f89048e6d368929015a0c739f\">albumbrowse_complete_cb</a> *callback, void *userdata)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">bool&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__albumbrowse.html#gad618d2752eb55173ab373d1407971960\">sp_albumbrowse_is_loaded</a> (<a class=\"el\" href=\"group__types.html#ga9c4550473a7a07790778ba870c31b4d9\">sp_albumbrowse</a> *alb)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__error.html#gafd27986ce4cd9eeaeca8adda83c9eb6b\">sp_error</a>&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__albumbrowse.html#ga153417eee319e7711b66503f88fba88b\">sp_albumbrowse_error</a> (<a class=\"el\" href=\"group__types.html#ga9c4550473a7a07790778ba870c31b4d9\">sp_albumbrowse</a> *alb)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__types.html#ga6fd3e5de729c429fef3ff18ece6dcfad\">sp_album</a> *&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__albumbrowse.html#gaf0dadfc4edb48a3558b606e30e8bedfa\">sp_albumbrowse_album</a> (<a class=\"el\" href=\"group__types.html#ga9c4550473a7a07790778ba870c31b4d9\">sp_albumbrowse</a> *alb)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__types.html#ga31764fbd69618c10be173c6c03d4c1bc\">sp_artist</a> *&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__albumbrowse.html#ga4f835537a65bcac9ec52cef1058a44bc\">sp_albumbrowse_artist</a> (<a class=\"el\" href=\"group__types.html#ga9c4550473a7a07790778ba870c31b4d9\">sp_albumbrowse</a> *alb)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">int&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__albumbrowse.html#gab53fa74ee1958dad5186be09e70ddc4a\">sp_albumbrowse_num_copyrights</a> (<a class=\"el\" href=\"group__types.html#ga9c4550473a7a07790778ba870c31b4d9\">sp_albumbrowse</a> *alb)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">const char *&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__albumbrowse.html#ga34b205daa2960e8d02a6e1accd80ab92\">sp_albumbrowse_copyright</a> (<a class=\"el\" href=\"group__types.html#ga9c4550473a7a07790778ba870c31b4d9\">sp_albumbrowse</a> *alb, int index)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">int&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__albumbrowse.html#ga3fb91de745ca07d3801a57288f2d9da7\">sp_albumbrowse_num_tracks</a> (<a class=\"el\" href=\"group__types.html#ga9c4550473a7a07790778ba870c31b4d9\">sp_albumbrowse</a> *alb)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__types.html#ga47bbd2262f0c8b5d7147af7d62198e48\">sp_track</a> *&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__albumbrowse.html#gad3c8df4b75158bba2c06aaefa74c5aa1\">sp_albumbrowse_track</a> (<a class=\"el\" href=\"group__types.html#ga9c4550473a7a07790778ba870c31b4d9\">sp_albumbrowse</a> *alb, int index)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">const char *&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__albumbrowse.html#ga868f3f3263f5033ae1fba60f403be712\">sp_albumbrowse_review</a> (<a class=\"el\" href=\"group__types.html#ga9c4550473a7a07790778ba870c31b4d9\">sp_albumbrowse</a> *alb)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">int&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__albumbrowse.html#ga2f1e1049065e8c090c010f8e43061bd4\">sp_albumbrowse_backend_request_duration</a> (<a class=\"el\" href=\"group__types.html#ga9c4550473a7a07790778ba870c31b4d9\">sp_albumbrowse</a> *alb)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__error.html#gafd27986ce4cd9eeaeca8adda83c9eb6b\">sp_error</a>&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__albumbrowse.html#ga1afd6a10febf31a61cf356673cb34bef\">sp_albumbrowse_add_ref</a> (<a class=\"el\" href=\"group__types.html#ga9c4550473a7a07790778ba870c31b4d9\">sp_albumbrowse</a> *alb)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__error.html#gafd27986ce4cd9eeaeca8adda83c9eb6b\">sp_error</a>&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__albumbrowse.html#gabdd5a4e3b2098166b67e35979f59613d\">sp_albumbrowse_release</a> (<a class=\"el\" href=\"group__types.html#ga9c4550473a7a07790778ba870c31b4d9\">sp_albumbrowse</a> *alb)</td></tr>\n</table>\n<hr/><a name=\"_details\"></a><h2>Detailed Description</h2>\n<p>Browsing adds additional information to what an <a class=\"el\" href=\"group__types.html#ga6fd3e5de729c429fef3ff18ece6dcfad\" title=\"An album handle.\">sp_album</a> holds. It retrieves copyrights, reviews and tracks of the album. </p>\n<hr/><h2>Typedef Documentation</h2>\n<a class=\"anchor\" id=\"gabd76254f89048e6d368929015a0c739f\"></a><!-- doxytag: member=\"api.h::albumbrowse_complete_cb\" ref=\"gabd76254f89048e6d368929015a0c739f\" args=\"(sp_albumbrowse *result, void *userdata)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\">typedef void <a class=\"el\" href=\"group__albumbrowse.html#gabd76254f89048e6d368929015a0c739f\">albumbrowse_complete_cb</a>(<a class=\"el\" href=\"group__types.html#ga9c4550473a7a07790778ba870c31b4d9\">sp_albumbrowse</a> *result, void *userdata)</td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>The type of a callback used in <a class=\"el\" href=\"group__albumbrowse.html#gaf1bc3042e748efea5ca7ac159e5cbfbe\">sp_albumbrowse_create()</a></p>\n<p>When the callback is called, the metadata of all tracks belonging to it will have been loaded, so <a class=\"el\" href=\"group__track.html#ga8b69cf193679c7e00031ae43e61c6a54\">sp_track_is_loaded()</a> will return non-zero. The <a class=\"el\" href=\"group__types.html#ga31764fbd69618c10be173c6c03d4c1bc\" title=\"An artist handle.\">sp_artist</a> of the album will also have been fully loaded.</p>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>result</em>&nbsp;</td><td>The same pointer returned by <a class=\"el\" href=\"group__albumbrowse.html#gaf1bc3042e748efea5ca7ac159e5cbfbe\">sp_albumbrowse_create()</a> </td></tr>\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>userdata</em>&nbsp;</td><td>The opaque pointer given to <a class=\"el\" href=\"group__albumbrowse.html#gaf1bc3042e748efea5ca7ac159e5cbfbe\">sp_albumbrowse_create()</a> </td></tr>\n  </table>\n  </dd>\n</dl>\n\n</div>\n</div>\n<hr/><h2>Function Documentation</h2>\n<a class=\"anchor\" id=\"ga1afd6a10febf31a61cf356673cb34bef\"></a><!-- doxytag: member=\"api.h::sp_albumbrowse_add_ref\" ref=\"ga1afd6a10febf31a61cf356673cb34bef\" args=\"(sp_albumbrowse *alb)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\"><a class=\"el\" href=\"group__error.html#gafd27986ce4cd9eeaeca8adda83c9eb6b\">sp_error</a> sp_albumbrowse_add_ref </td>\n          <td>(</td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__types.html#ga9c4550473a7a07790778ba870c31b4d9\">sp_albumbrowse</a> *&nbsp;</td>\n          <td class=\"paramname\"> <em>alb</em></td>\n          <td>&nbsp;)&nbsp;</td>\n          <td></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Increase the reference count of an album browse result</p>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>alb</em>&nbsp;</td><td>The album browse result object </td></tr>\n  </table>\n  </dd>\n</dl>\n<dl class=\"return\"><dt><b>Returns:</b></dt><dd>One of the following errors, from <a class=\"el\" href=\"group__error.html#ga83154178d3a32668658734d2facfa22b\">sp_error</a> SP_ERROR_OK </dd></dl>\n\n</div>\n</div>\n<a class=\"anchor\" id=\"gaf0dadfc4edb48a3558b606e30e8bedfa\"></a><!-- doxytag: member=\"api.h::sp_albumbrowse_album\" ref=\"gaf0dadfc4edb48a3558b606e30e8bedfa\" args=\"(sp_albumbrowse *alb)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\"><a class=\"el\" href=\"group__types.html#ga6fd3e5de729c429fef3ff18ece6dcfad\">sp_album</a>* sp_albumbrowse_album </td>\n          <td>(</td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__types.html#ga9c4550473a7a07790778ba870c31b4d9\">sp_albumbrowse</a> *&nbsp;</td>\n          <td class=\"paramname\"> <em>alb</em></td>\n          <td>&nbsp;)&nbsp;</td>\n          <td></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Given an album browse object, return the pointer to its album object</p>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>alb</em>&nbsp;</td><td>Album browse object</td></tr>\n  </table>\n  </dd>\n</dl>\n<dl class=\"return\"><dt><b>Returns:</b></dt><dd>Album object </dd></dl>\n<dl><dt><b>Examples: </b></dt><dd><a class=\"el\" href=\"browse_8c-example.html#a14\">browse.c</a>.</dd>\n</dl>\n</div>\n</div>\n<a class=\"anchor\" id=\"ga4f835537a65bcac9ec52cef1058a44bc\"></a><!-- doxytag: member=\"api.h::sp_albumbrowse_artist\" ref=\"ga4f835537a65bcac9ec52cef1058a44bc\" args=\"(sp_albumbrowse *alb)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\"><a class=\"el\" href=\"group__types.html#ga31764fbd69618c10be173c6c03d4c1bc\">sp_artist</a>* sp_albumbrowse_artist </td>\n          <td>(</td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__types.html#ga9c4550473a7a07790778ba870c31b4d9\">sp_albumbrowse</a> *&nbsp;</td>\n          <td class=\"paramname\"> <em>alb</em></td>\n          <td>&nbsp;)&nbsp;</td>\n          <td></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Given an album browse object, return the pointer to its artist object</p>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>alb</em>&nbsp;</td><td>Album browse object</td></tr>\n  </table>\n  </dd>\n</dl>\n<dl class=\"return\"><dt><b>Returns:</b></dt><dd>Artist object </dd></dl>\n\n</div>\n</div>\n<a class=\"anchor\" id=\"ga2f1e1049065e8c090c010f8e43061bd4\"></a><!-- doxytag: member=\"api.h::sp_albumbrowse_backend_request_duration\" ref=\"ga2f1e1049065e8c090c010f8e43061bd4\" args=\"(sp_albumbrowse *alb)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\">int sp_albumbrowse_backend_request_duration </td>\n          <td>(</td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__types.html#ga9c4550473a7a07790778ba870c31b4d9\">sp_albumbrowse</a> *&nbsp;</td>\n          <td class=\"paramname\"> <em>alb</em></td>\n          <td>&nbsp;)&nbsp;</td>\n          <td></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Return the time (in ms) that was spent waiting for the Spotify backend to serve the request</p>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>alb</em>&nbsp;</td><td>Album browse object</td></tr>\n  </table>\n  </dd>\n</dl>\n<dl class=\"return\"><dt><b>Returns:</b></dt><dd>-1 if the request was served from the local cache If the result is not yet loaded the return value is undefined </dd></dl>\n\n</div>\n</div>\n<a class=\"anchor\" id=\"ga34b205daa2960e8d02a6e1accd80ab92\"></a><!-- doxytag: member=\"api.h::sp_albumbrowse_copyright\" ref=\"ga34b205daa2960e8d02a6e1accd80ab92\" args=\"(sp_albumbrowse *alb, int index)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\">const char* sp_albumbrowse_copyright </td>\n          <td>(</td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__types.html#ga9c4550473a7a07790778ba870c31b4d9\">sp_albumbrowse</a> *&nbsp;</td>\n          <td class=\"paramname\"> <em>alb</em>, </td>\n        </tr>\n        <tr>\n          <td class=\"paramkey\"></td>\n          <td></td>\n          <td class=\"paramtype\">int&nbsp;</td>\n          <td class=\"paramname\"> <em>index</em></td><td>&nbsp;</td>\n        </tr>\n        <tr>\n          <td></td>\n          <td>)</td>\n          <td></td><td></td><td></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Given an album browse object, return one of its copyright strings</p>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>alb</em>&nbsp;</td><td>Album browse object </td></tr>\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>index</em>&nbsp;</td><td>The index for the copyright string. Should be in the interval [0, <a class=\"el\" href=\"group__albumbrowse.html#gab53fa74ee1958dad5186be09e70ddc4a\">sp_albumbrowse_num_copyrights()</a> - 1]</td></tr>\n  </table>\n  </dd>\n</dl>\n<dl class=\"return\"><dt><b>Returns:</b></dt><dd>Copyright string in UTF-8 format, or NULL if the index is invalid. Returned string is valid as long as the album object stays allocated and no longer than the next call to <a class=\"el\" href=\"group__session.html#gaff27cb730db6debf55e750e39e7fadd7\">sp_session_process_events()</a> </dd></dl>\n<dl><dt><b>Examples: </b></dt><dd><a class=\"el\" href=\"browse_8c-example.html#a17\">browse.c</a>.</dd>\n</dl>\n</div>\n</div>\n<a class=\"anchor\" id=\"gaf1bc3042e748efea5ca7ac159e5cbfbe\"></a><!-- doxytag: member=\"api.h::sp_albumbrowse_create\" ref=\"gaf1bc3042e748efea5ca7ac159e5cbfbe\" args=\"(sp_session *session, sp_album *album, albumbrowse_complete_cb *callback, void *userdata)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\"><a class=\"el\" href=\"group__types.html#ga9c4550473a7a07790778ba870c31b4d9\">sp_albumbrowse</a>* sp_albumbrowse_create </td>\n          <td>(</td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__types.html#ga70dd19c6f824cf6a159575aa4c128b53\">sp_session</a> *&nbsp;</td>\n          <td class=\"paramname\"> <em>session</em>, </td>\n        </tr>\n        <tr>\n          <td class=\"paramkey\"></td>\n          <td></td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__types.html#ga6fd3e5de729c429fef3ff18ece6dcfad\">sp_album</a> *&nbsp;</td>\n          <td class=\"paramname\"> <em>album</em>, </td>\n        </tr>\n        <tr>\n          <td class=\"paramkey\"></td>\n          <td></td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__albumbrowse.html#gabd76254f89048e6d368929015a0c739f\">albumbrowse_complete_cb</a> *&nbsp;</td>\n          <td class=\"paramname\"> <em>callback</em>, </td>\n        </tr>\n        <tr>\n          <td class=\"paramkey\"></td>\n          <td></td>\n          <td class=\"paramtype\">void *&nbsp;</td>\n          <td class=\"paramname\"> <em>userdata</em></td><td>&nbsp;</td>\n        </tr>\n        <tr>\n          <td></td>\n          <td>)</td>\n          <td></td><td></td><td></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Initiate a request for browsing an album</p>\n<p>The user is responsible for freeing the returned album browse using <a class=\"el\" href=\"group__albumbrowse.html#gabdd5a4e3b2098166b67e35979f59613d\">sp_albumbrowse_release()</a>. This can be done in the callback.</p>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>session</em>&nbsp;</td><td>Session object </td></tr>\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>album</em>&nbsp;</td><td>Album to be browsed. The album metadata does not have to be loaded </td></tr>\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>callback</em>&nbsp;</td><td>Callback to be invoked when browsing has been completed. Pass NULL if you are not interested in this event. </td></tr>\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>userdata</em>&nbsp;</td><td>Userdata passed to callback.</td></tr>\n  </table>\n  </dd>\n</dl>\n<dl class=\"return\"><dt><b>Returns:</b></dt><dd>Album browse object</dd></dl>\n<dl class=\"see\"><dt><b>See also:</b></dt><dd><a class=\"el\" href=\"group__albumbrowse.html#gabd76254f89048e6d368929015a0c739f\">albumbrowse_complete_cb</a> </dd></dl>\n<dl><dt><b>Examples: </b></dt><dd><a class=\"el\" href=\"browse_8c-example.html#a48\">browse.c</a>.</dd>\n</dl>\n</div>\n</div>\n<a class=\"anchor\" id=\"ga153417eee319e7711b66503f88fba88b\"></a><!-- doxytag: member=\"api.h::sp_albumbrowse_error\" ref=\"ga153417eee319e7711b66503f88fba88b\" args=\"(sp_albumbrowse *alb)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\"><a class=\"el\" href=\"group__error.html#gafd27986ce4cd9eeaeca8adda83c9eb6b\">sp_error</a> sp_albumbrowse_error </td>\n          <td>(</td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__types.html#ga9c4550473a7a07790778ba870c31b4d9\">sp_albumbrowse</a> *&nbsp;</td>\n          <td class=\"paramname\"> <em>alb</em></td>\n          <td>&nbsp;)&nbsp;</td>\n          <td></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Check if browsing returned an error code.</p>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>alb</em>&nbsp;</td><td>Album browse object</td></tr>\n  </table>\n  </dd>\n</dl>\n<dl class=\"return\"><dt><b>Returns:</b></dt><dd>One of the following errors, from <a class=\"el\" href=\"group__error.html#ga83154178d3a32668658734d2facfa22b\">sp_error</a> SP_ERROR_OK SP_ERROR_IS_LOADING SP_ERROR_OTHER_PERMANENT SP_ERROR_OTHER_TRANSIENT </dd></dl>\n<dl><dt><b>Examples: </b></dt><dd><a class=\"el\" href=\"browse_8c-example.html#a28\">browse.c</a>.</dd>\n</dl>\n</div>\n</div>\n<a class=\"anchor\" id=\"gad618d2752eb55173ab373d1407971960\"></a><!-- doxytag: member=\"api.h::sp_albumbrowse_is_loaded\" ref=\"gad618d2752eb55173ab373d1407971960\" args=\"(sp_albumbrowse *alb)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\">bool sp_albumbrowse_is_loaded </td>\n          <td>(</td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__types.html#ga9c4550473a7a07790778ba870c31b4d9\">sp_albumbrowse</a> *&nbsp;</td>\n          <td class=\"paramname\"> <em>alb</em></td>\n          <td>&nbsp;)&nbsp;</td>\n          <td></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Check if an album browse request is completed</p>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>alb</em>&nbsp;</td><td>Album browse object</td></tr>\n  </table>\n  </dd>\n</dl>\n<dl class=\"return\"><dt><b>Returns:</b></dt><dd>True if browsing is completed, false if not </dd></dl>\n\n</div>\n</div>\n<a class=\"anchor\" id=\"gab53fa74ee1958dad5186be09e70ddc4a\"></a><!-- doxytag: member=\"api.h::sp_albumbrowse_num_copyrights\" ref=\"gab53fa74ee1958dad5186be09e70ddc4a\" args=\"(sp_albumbrowse *alb)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\">int sp_albumbrowse_num_copyrights </td>\n          <td>(</td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__types.html#ga9c4550473a7a07790778ba870c31b4d9\">sp_albumbrowse</a> *&nbsp;</td>\n          <td class=\"paramname\"> <em>alb</em></td>\n          <td>&nbsp;)&nbsp;</td>\n          <td></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Given an album browse object, return number of copyright strings</p>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>alb</em>&nbsp;</td><td>Album browse object</td></tr>\n  </table>\n  </dd>\n</dl>\n<dl class=\"return\"><dt><b>Returns:</b></dt><dd>Number of copyright strings available, 0 if unknown </dd></dl>\n<dl><dt><b>Examples: </b></dt><dd><a class=\"el\" href=\"browse_8c-example.html#a16\">browse.c</a>.</dd>\n</dl>\n</div>\n</div>\n<a class=\"anchor\" id=\"ga3fb91de745ca07d3801a57288f2d9da7\"></a><!-- doxytag: member=\"api.h::sp_albumbrowse_num_tracks\" ref=\"ga3fb91de745ca07d3801a57288f2d9da7\" args=\"(sp_albumbrowse *alb)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\">int sp_albumbrowse_num_tracks </td>\n          <td>(</td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__types.html#ga9c4550473a7a07790778ba870c31b4d9\">sp_albumbrowse</a> *&nbsp;</td>\n          <td class=\"paramname\"> <em>alb</em></td>\n          <td>&nbsp;)&nbsp;</td>\n          <td></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Given an album browse object, return number of tracks</p>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>alb</em>&nbsp;</td><td>Album browse object</td></tr>\n  </table>\n  </dd>\n</dl>\n<dl class=\"return\"><dt><b>Returns:</b></dt><dd>Number of tracks on album </dd></dl>\n<dl><dt><b>Examples: </b></dt><dd><a class=\"el\" href=\"browse_8c-example.html#a18\">browse.c</a>.</dd>\n</dl>\n</div>\n</div>\n<a class=\"anchor\" id=\"gabdd5a4e3b2098166b67e35979f59613d\"></a><!-- doxytag: member=\"api.h::sp_albumbrowse_release\" ref=\"gabdd5a4e3b2098166b67e35979f59613d\" args=\"(sp_albumbrowse *alb)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\"><a class=\"el\" href=\"group__error.html#gafd27986ce4cd9eeaeca8adda83c9eb6b\">sp_error</a> sp_albumbrowse_release </td>\n          <td>(</td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__types.html#ga9c4550473a7a07790778ba870c31b4d9\">sp_albumbrowse</a> *&nbsp;</td>\n          <td class=\"paramname\"> <em>alb</em></td>\n          <td>&nbsp;)&nbsp;</td>\n          <td></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Decrease the reference count of an album browse result</p>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>alb</em>&nbsp;</td><td>The album browse result object </td></tr>\n  </table>\n  </dd>\n</dl>\n<dl class=\"return\"><dt><b>Returns:</b></dt><dd>One of the following errors, from <a class=\"el\" href=\"group__error.html#ga83154178d3a32668658734d2facfa22b\">sp_error</a> SP_ERROR_OK </dd></dl>\n<dl><dt><b>Examples: </b></dt><dd><a class=\"el\" href=\"browse_8c-example.html#a31\">browse.c</a>.</dd>\n</dl>\n</div>\n</div>\n<a class=\"anchor\" id=\"ga868f3f3263f5033ae1fba60f403be712\"></a><!-- doxytag: member=\"api.h::sp_albumbrowse_review\" ref=\"ga868f3f3263f5033ae1fba60f403be712\" args=\"(sp_albumbrowse *alb)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\">const char* sp_albumbrowse_review </td>\n          <td>(</td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__types.html#ga9c4550473a7a07790778ba870c31b4d9\">sp_albumbrowse</a> *&nbsp;</td>\n          <td class=\"paramname\"> <em>alb</em></td>\n          <td>&nbsp;)&nbsp;</td>\n          <td></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Given an album browse object, return its review</p>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>alb</em>&nbsp;</td><td>Album browse object</td></tr>\n  </table>\n  </dd>\n</dl>\n<dl class=\"return\"><dt><b>Returns:</b></dt><dd>Review string in UTF-8 format. Returned string is valid as long as the album object stays allocated and no longer than the next call to <a class=\"el\" href=\"group__session.html#gaff27cb730db6debf55e750e39e7fadd7\">sp_session_process_events()</a> </dd></dl>\n<dl><dt><b>Examples: </b></dt><dd><a class=\"el\" href=\"browse_8c-example.html#a19\">browse.c</a>.</dd>\n</dl>\n</div>\n</div>\n<a class=\"anchor\" id=\"gad3c8df4b75158bba2c06aaefa74c5aa1\"></a><!-- doxytag: member=\"api.h::sp_albumbrowse_track\" ref=\"gad3c8df4b75158bba2c06aaefa74c5aa1\" args=\"(sp_albumbrowse *alb, int index)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\"><a class=\"el\" href=\"group__types.html#ga47bbd2262f0c8b5d7147af7d62198e48\">sp_track</a>* sp_albumbrowse_track </td>\n          <td>(</td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__types.html#ga9c4550473a7a07790778ba870c31b4d9\">sp_albumbrowse</a> *&nbsp;</td>\n          <td class=\"paramname\"> <em>alb</em>, </td>\n        </tr>\n        <tr>\n          <td class=\"paramkey\"></td>\n          <td></td>\n          <td class=\"paramtype\">int&nbsp;</td>\n          <td class=\"paramname\"> <em>index</em></td><td>&nbsp;</td>\n        </tr>\n        <tr>\n          <td></td>\n          <td>)</td>\n          <td></td><td></td><td></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Given an album browse object, return a pointer to one of its tracks</p>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>alb</em>&nbsp;</td><td>Album browse object </td></tr>\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>index</em>&nbsp;</td><td>The index for the track. Should be in the interval [0, <a class=\"el\" href=\"group__albumbrowse.html#ga3fb91de745ca07d3801a57288f2d9da7\">sp_albumbrowse_num_tracks()</a> - 1]</td></tr>\n  </table>\n  </dd>\n</dl>\n<dl class=\"return\"><dt><b>Returns:</b></dt><dd>A track.</dd></dl>\n<dl class=\"see\"><dt><b>See also:</b></dt><dd><a class=\"el\" href=\"group__track.html\">Track subsystem</a> </dd></dl>\n<dl><dt><b>Examples: </b></dt><dd><a class=\"el\" href=\"browse_8c-example.html#a20\">browse.c</a>.</dd>\n</dl>\n</div>\n</div>\n</div>\n<hr size=\"1\"><address style=\"text-align: right;\"><small>\nGenerated on Wed Jun 13 2012 14:22:40.<br>\nCopyright &copy; 2006&ndash;2012 Spotify Ltd</small></address>\n</body>\n</html>\n"
  },
  {
    "path": "libspotify/docs/html/group__artist.html",
    "content": "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\n<html xmlns=\"http://www.w3.org/1999/xhtml\">\n<head>\n<meta http-equiv=\"Content-Type\" content=\"text/xhtml;charset=UTF-8\"/>\n<title>libspotify: Artist subsystem</title>\n<link href=\"tabs.css\" rel=\"stylesheet\" type=\"text/css\"/>\n<link href=\"doxygen.css\" rel=\"stylesheet\" type=\"text/css\"/>\n</head>\n<body>\n<!-- Generated by Doxygen 1.7.1 -->\n<div class=\"navigation\" id=\"top\">\n  <div class=\"tabs\">\n    <ul class=\"tablist\">\n      <li><a href=\"index.html\"><span>Main&nbsp;Page</span></a></li>\n      <li><a href=\"modules.html\"><span>Modules</span></a></li>\n      <li><a href=\"annotated.html\"><span>Data&nbsp;Structures</span></a></li>\n      <li><a href=\"files.html\"><span>Files</span></a></li>\n      <li><a href=\"examples.html\"><span>Examples</span></a></li>\n    </ul>\n  </div>\n</div>\n<div class=\"header\">\n  <div class=\"summary\">\n<a href=\"#func-members\">Functions</a>  </div>\n  <div class=\"headertitle\">\n<h1>Artist subsystem</h1>  </div>\n</div>\n<div class=\"contents\">\n<table class=\"memberdecls\">\n<tr><td colspan=\"2\"><h2><a name=\"func-members\"></a>\nFunctions</h2></td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">const char *&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__artist.html#gad2895555bb48514986823733a7afe5e2\">sp_artist_name</a> (<a class=\"el\" href=\"group__types.html#ga31764fbd69618c10be173c6c03d4c1bc\">sp_artist</a> *artist)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">bool&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__artist.html#gafc98f5093184a7ac7ce608302b0971ea\">sp_artist_is_loaded</a> (<a class=\"el\" href=\"group__types.html#ga31764fbd69618c10be173c6c03d4c1bc\">sp_artist</a> *artist)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">const byte *&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__artist.html#ga87d366ac7479c717005c2c059d5f2be9\">sp_artist_portrait</a> (<a class=\"el\" href=\"group__types.html#ga31764fbd69618c10be173c6c03d4c1bc\">sp_artist</a> *artist, <a class=\"el\" href=\"group__session.html#ga61bc424465d776af3ceeb69eee2bb492\">sp_image_size</a> size)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__error.html#gafd27986ce4cd9eeaeca8adda83c9eb6b\">sp_error</a>&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__artist.html#gac70d7467f580aa497d1a5d610e06d273\">sp_artist_add_ref</a> (<a class=\"el\" href=\"group__types.html#ga31764fbd69618c10be173c6c03d4c1bc\">sp_artist</a> *artist)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__error.html#gafd27986ce4cd9eeaeca8adda83c9eb6b\">sp_error</a>&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__artist.html#ga7b0da8f7ce09454bd0821d06d52e2d12\">sp_artist_release</a> (<a class=\"el\" href=\"group__types.html#ga31764fbd69618c10be173c6c03d4c1bc\">sp_artist</a> *artist)</td></tr>\n</table>\n<hr/><h2>Function Documentation</h2>\n<a class=\"anchor\" id=\"gac70d7467f580aa497d1a5d610e06d273\"></a><!-- doxytag: member=\"api.h::sp_artist_add_ref\" ref=\"gac70d7467f580aa497d1a5d610e06d273\" args=\"(sp_artist *artist)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\"><a class=\"el\" href=\"group__error.html#gafd27986ce4cd9eeaeca8adda83c9eb6b\">sp_error</a> sp_artist_add_ref </td>\n          <td>(</td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__types.html#ga31764fbd69618c10be173c6c03d4c1bc\">sp_artist</a> *&nbsp;</td>\n          <td class=\"paramname\"> <em>artist</em></td>\n          <td>&nbsp;)&nbsp;</td>\n          <td></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Increase the reference count of a artist</p>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>artist</em>&nbsp;</td><td>The artist object </td></tr>\n  </table>\n  </dd>\n</dl>\n<dl class=\"return\"><dt><b>Returns:</b></dt><dd>One of the following errors, from <a class=\"el\" href=\"group__error.html#ga83154178d3a32668658734d2facfa22b\">sp_error</a> SP_ERROR_OK </dd></dl>\n\n</div>\n</div>\n<a class=\"anchor\" id=\"gafc98f5093184a7ac7ce608302b0971ea\"></a><!-- doxytag: member=\"api.h::sp_artist_is_loaded\" ref=\"gafc98f5093184a7ac7ce608302b0971ea\" args=\"(sp_artist *artist)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\">bool sp_artist_is_loaded </td>\n          <td>(</td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__types.html#ga31764fbd69618c10be173c6c03d4c1bc\">sp_artist</a> *&nbsp;</td>\n          <td class=\"paramname\"> <em>artist</em></td>\n          <td>&nbsp;)&nbsp;</td>\n          <td></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Check if the artist object is populated with data</p>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>artist</em>&nbsp;</td><td>An artist object</td></tr>\n  </table>\n  </dd>\n</dl>\n<dl class=\"return\"><dt><b>Returns:</b></dt><dd>True if metadata is present, false if not </dd></dl>\n\n</div>\n</div>\n<a class=\"anchor\" id=\"gad2895555bb48514986823733a7afe5e2\"></a><!-- doxytag: member=\"api.h::sp_artist_name\" ref=\"gad2895555bb48514986823733a7afe5e2\" args=\"(sp_artist *artist)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\">const char* sp_artist_name </td>\n          <td>(</td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__types.html#ga31764fbd69618c10be173c6c03d4c1bc\">sp_artist</a> *&nbsp;</td>\n          <td class=\"paramname\"> <em>artist</em></td>\n          <td>&nbsp;)&nbsp;</td>\n          <td></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Return name of artist</p>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>artist</em>&nbsp;</td><td>Artist object</td></tr>\n  </table>\n  </dd>\n</dl>\n<dl class=\"return\"><dt><b>Returns:</b></dt><dd>Name of artist. Returned string is valid as long as the artist object stays allocated and no longer than the next call to <a class=\"el\" href=\"group__session.html#gaff27cb730db6debf55e750e39e7fadd7\">sp_session_process_events()</a> </dd></dl>\n<dl><dt><b>Examples: </b></dt><dd><a class=\"el\" href=\"browse_8c-example.html#a9\">browse.c</a>, <a class=\"el\" href=\"search_8c-example.html#a2\">search.c</a>, and <a class=\"el\" href=\"toplist_8c-example.html#a1\">toplist.c</a>.</dd>\n</dl>\n</div>\n</div>\n<a class=\"anchor\" id=\"ga87d366ac7479c717005c2c059d5f2be9\"></a><!-- doxytag: member=\"api.h::sp_artist_portrait\" ref=\"ga87d366ac7479c717005c2c059d5f2be9\" args=\"(sp_artist *artist, sp_image_size size)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\">const byte* sp_artist_portrait </td>\n          <td>(</td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__types.html#ga31764fbd69618c10be173c6c03d4c1bc\">sp_artist</a> *&nbsp;</td>\n          <td class=\"paramname\"> <em>artist</em>, </td>\n        </tr>\n        <tr>\n          <td class=\"paramkey\"></td>\n          <td></td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__session.html#ga61bc424465d776af3ceeb69eee2bb492\">sp_image_size</a>&nbsp;</td>\n          <td class=\"paramname\"> <em>size</em></td><td>&nbsp;</td>\n        </tr>\n        <tr>\n          <td></td>\n          <td>)</td>\n          <td></td><td></td><td></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Return portrait for artist</p>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>artist</em>&nbsp;</td><td>The artist object </td></tr>\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>size</em>&nbsp;</td><td>The desired size of the image</td></tr>\n  </table>\n  </dd>\n</dl>\n<dl class=\"return\"><dt><b>Returns:</b></dt><dd>ID byte sequence that can be passed to <a class=\"el\" href=\"group__image.html#gaf29e89f45945db2b3667bf9db4279c33\">sp_image_create()</a> If the artist has no image or the metadata for the album is not loaded yet, this function returns NULL. </dd></dl>\n\n</div>\n</div>\n<a class=\"anchor\" id=\"ga7b0da8f7ce09454bd0821d06d52e2d12\"></a><!-- doxytag: member=\"api.h::sp_artist_release\" ref=\"ga7b0da8f7ce09454bd0821d06d52e2d12\" args=\"(sp_artist *artist)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\"><a class=\"el\" href=\"group__error.html#gafd27986ce4cd9eeaeca8adda83c9eb6b\">sp_error</a> sp_artist_release </td>\n          <td>(</td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__types.html#ga31764fbd69618c10be173c6c03d4c1bc\">sp_artist</a> *&nbsp;</td>\n          <td class=\"paramname\"> <em>artist</em></td>\n          <td>&nbsp;)&nbsp;</td>\n          <td></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Decrease the reference count of a artist</p>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>artist</em>&nbsp;</td><td>The artist object </td></tr>\n  </table>\n  </dd>\n</dl>\n<dl class=\"return\"><dt><b>Returns:</b></dt><dd>One of the following errors, from <a class=\"el\" href=\"group__error.html#ga83154178d3a32668658734d2facfa22b\">sp_error</a> SP_ERROR_OK </dd></dl>\n\n</div>\n</div>\n</div>\n<hr size=\"1\"><address style=\"text-align: right;\"><small>\nGenerated on Wed Jun 13 2012 14:22:40.<br>\nCopyright &copy; 2006&ndash;2012 Spotify Ltd</small></address>\n</body>\n</html>\n"
  },
  {
    "path": "libspotify/docs/html/group__artistbrowse.html",
    "content": "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\n<html xmlns=\"http://www.w3.org/1999/xhtml\">\n<head>\n<meta http-equiv=\"Content-Type\" content=\"text/xhtml;charset=UTF-8\"/>\n<title>libspotify: Artist browsing</title>\n<link href=\"tabs.css\" rel=\"stylesheet\" type=\"text/css\"/>\n<link href=\"doxygen.css\" rel=\"stylesheet\" type=\"text/css\"/>\n</head>\n<body>\n<!-- Generated by Doxygen 1.7.1 -->\n<div class=\"navigation\" id=\"top\">\n  <div class=\"tabs\">\n    <ul class=\"tablist\">\n      <li><a href=\"index.html\"><span>Main&nbsp;Page</span></a></li>\n      <li><a href=\"modules.html\"><span>Modules</span></a></li>\n      <li><a href=\"annotated.html\"><span>Data&nbsp;Structures</span></a></li>\n      <li><a href=\"files.html\"><span>Files</span></a></li>\n      <li><a href=\"examples.html\"><span>Examples</span></a></li>\n    </ul>\n  </div>\n</div>\n<div class=\"header\">\n  <div class=\"summary\">\n<a href=\"#typedef-members\">Typedefs</a> &#124;\n<a href=\"#func-members\">Functions</a>  </div>\n  <div class=\"headertitle\">\n<h1>Artist browsing</h1>  </div>\n</div>\n<div class=\"contents\">\n<table class=\"memberdecls\">\n<tr><td colspan=\"2\"><h2><a name=\"typedef-members\"></a>\nTypedefs</h2></td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">typedef void&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__artistbrowse.html#ga8077aa18c043210e859479be2616a3e7\">artistbrowse_complete_cb</a> (<a class=\"el\" href=\"group__types.html#gafd3d5aae485f1012ec91b7948e6f9f2b\">sp_artistbrowse</a> *result, void *userdata)</td></tr>\n<tr><td colspan=\"2\"><h2><a name=\"func-members\"></a>\nFunctions</h2></td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__types.html#gafd3d5aae485f1012ec91b7948e6f9f2b\">sp_artistbrowse</a> *&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__artistbrowse.html#ga8dd8364b2fcd29c846209660bd9a69b2\">sp_artistbrowse_create</a> (<a class=\"el\" href=\"group__types.html#ga70dd19c6f824cf6a159575aa4c128b53\">sp_session</a> *session, <a class=\"el\" href=\"group__types.html#ga31764fbd69618c10be173c6c03d4c1bc\">sp_artist</a> *artist, <a class=\"el\" href=\"group__session.html#gac86504cc9e8cadbc30c8aa8dbf355034\">sp_artistbrowse_type</a> type, <a class=\"el\" href=\"group__artistbrowse.html#ga8077aa18c043210e859479be2616a3e7\">artistbrowse_complete_cb</a> *callback, void *userdata)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">bool&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__artistbrowse.html#ga966b0f59e7b2b3d0037e44bb49dcdabc\">sp_artistbrowse_is_loaded</a> (<a class=\"el\" href=\"group__types.html#gafd3d5aae485f1012ec91b7948e6f9f2b\">sp_artistbrowse</a> *arb)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__error.html#gafd27986ce4cd9eeaeca8adda83c9eb6b\">sp_error</a>&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__artistbrowse.html#ga203e757088ff7a5098f16a1367da25d2\">sp_artistbrowse_error</a> (<a class=\"el\" href=\"group__types.html#gafd3d5aae485f1012ec91b7948e6f9f2b\">sp_artistbrowse</a> *arb)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__types.html#ga31764fbd69618c10be173c6c03d4c1bc\">sp_artist</a> *&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__artistbrowse.html#ga5f6a046b2bd261d7628582b986a9019f\">sp_artistbrowse_artist</a> (<a class=\"el\" href=\"group__types.html#gafd3d5aae485f1012ec91b7948e6f9f2b\">sp_artistbrowse</a> *arb)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">int&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__artistbrowse.html#ga98dc47d36d2789999bfe62707c5041d7\">sp_artistbrowse_num_portraits</a> (<a class=\"el\" href=\"group__types.html#gafd3d5aae485f1012ec91b7948e6f9f2b\">sp_artistbrowse</a> *arb)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">const byte *&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__artistbrowse.html#ga5f164b2f9609a7bf2c89b3a1407ec239\">sp_artistbrowse_portrait</a> (<a class=\"el\" href=\"group__types.html#gafd3d5aae485f1012ec91b7948e6f9f2b\">sp_artistbrowse</a> *arb, int index)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">int&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__artistbrowse.html#ga8c862caa2234125ffcc4e93287b1e029\">sp_artistbrowse_num_tracks</a> (<a class=\"el\" href=\"group__types.html#gafd3d5aae485f1012ec91b7948e6f9f2b\">sp_artistbrowse</a> *arb)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__types.html#ga47bbd2262f0c8b5d7147af7d62198e48\">sp_track</a> *&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__artistbrowse.html#ga45d28771a856f935dc40ab40e27dec4c\">sp_artistbrowse_track</a> (<a class=\"el\" href=\"group__types.html#gafd3d5aae485f1012ec91b7948e6f9f2b\">sp_artistbrowse</a> *arb, int index)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">int&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__artistbrowse.html#ga0c26782796af954300ce92fddea97637\">sp_artistbrowse_num_tophit_tracks</a> (<a class=\"el\" href=\"group__types.html#gafd3d5aae485f1012ec91b7948e6f9f2b\">sp_artistbrowse</a> *arb)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__types.html#ga47bbd2262f0c8b5d7147af7d62198e48\">sp_track</a> *&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__artistbrowse.html#ga5da55f43def03fe9f0d2c8b252b9755a\">sp_artistbrowse_tophit_track</a> (<a class=\"el\" href=\"group__types.html#gafd3d5aae485f1012ec91b7948e6f9f2b\">sp_artistbrowse</a> *arb, int index)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">int&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__artistbrowse.html#gaf0055361abd53425d89a4636a32b5c83\">sp_artistbrowse_num_albums</a> (<a class=\"el\" href=\"group__types.html#gafd3d5aae485f1012ec91b7948e6f9f2b\">sp_artistbrowse</a> *arb)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__types.html#ga6fd3e5de729c429fef3ff18ece6dcfad\">sp_album</a> *&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__artistbrowse.html#ga5b36c9a34876beea8fda8674b93d4fd3\">sp_artistbrowse_album</a> (<a class=\"el\" href=\"group__types.html#gafd3d5aae485f1012ec91b7948e6f9f2b\">sp_artistbrowse</a> *arb, int index)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">int&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__artistbrowse.html#ga2559638742416ac621af0e919e017d17\">sp_artistbrowse_num_similar_artists</a> (<a class=\"el\" href=\"group__types.html#gafd3d5aae485f1012ec91b7948e6f9f2b\">sp_artistbrowse</a> *arb)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__types.html#ga31764fbd69618c10be173c6c03d4c1bc\">sp_artist</a> *&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__artistbrowse.html#gac60ef4f9e006a920f1d72b6098743fbc\">sp_artistbrowse_similar_artist</a> (<a class=\"el\" href=\"group__types.html#gafd3d5aae485f1012ec91b7948e6f9f2b\">sp_artistbrowse</a> *arb, int index)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">const char *&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__artistbrowse.html#ga8b93b9e5630662855f35694280ba4d2b\">sp_artistbrowse_biography</a> (<a class=\"el\" href=\"group__types.html#gafd3d5aae485f1012ec91b7948e6f9f2b\">sp_artistbrowse</a> *arb)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">int&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__artistbrowse.html#gadce357748b82abce8a7b093882850fdb\">sp_artistbrowse_backend_request_duration</a> (<a class=\"el\" href=\"group__types.html#gafd3d5aae485f1012ec91b7948e6f9f2b\">sp_artistbrowse</a> *arb)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__error.html#gafd27986ce4cd9eeaeca8adda83c9eb6b\">sp_error</a>&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__artistbrowse.html#ga69fc2e1d2d5e8d91a724486cbfd0c4dc\">sp_artistbrowse_add_ref</a> (<a class=\"el\" href=\"group__types.html#gafd3d5aae485f1012ec91b7948e6f9f2b\">sp_artistbrowse</a> *arb)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__error.html#gafd27986ce4cd9eeaeca8adda83c9eb6b\">sp_error</a>&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__artistbrowse.html#ga14626a4f6a60b1caf61cb54c26783671\">sp_artistbrowse_release</a> (<a class=\"el\" href=\"group__types.html#gafd3d5aae485f1012ec91b7948e6f9f2b\">sp_artistbrowse</a> *arb)</td></tr>\n</table>\n<hr/><a name=\"_details\"></a><h2>Detailed Description</h2>\n<p>Artist browsing initiates the fetching of information for a certain artist.</p>\n<dl class=\"note\"><dt><b>Note:</b></dt><dd>There is currently no built-in functionality available for getting the albums belonging to an artist. For now, just iterate over all tracks and note the album to build a list of all albums. This feature will be added in a future version of the library. </dd></dl>\n<hr/><h2>Typedef Documentation</h2>\n<a class=\"anchor\" id=\"ga8077aa18c043210e859479be2616a3e7\"></a><!-- doxytag: member=\"api.h::artistbrowse_complete_cb\" ref=\"ga8077aa18c043210e859479be2616a3e7\" args=\"(sp_artistbrowse *result, void *userdata)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\">typedef void <a class=\"el\" href=\"group__artistbrowse.html#ga8077aa18c043210e859479be2616a3e7\">artistbrowse_complete_cb</a>(<a class=\"el\" href=\"group__types.html#gafd3d5aae485f1012ec91b7948e6f9f2b\">sp_artistbrowse</a> *result, void *userdata)</td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>The type of a callback used in <a class=\"el\" href=\"group__artistbrowse.html#ga8dd8364b2fcd29c846209660bd9a69b2\">sp_artistbrowse_create()</a></p>\n<p>When the callback is called, the metadata of all tracks belonging to it will have been loaded, so <a class=\"el\" href=\"group__track.html#ga8b69cf193679c7e00031ae43e61c6a54\">sp_track_is_loaded()</a> will return non-zero. The same goes for the similar artist data.</p>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>result</em>&nbsp;</td><td>The same pointer returned by <a class=\"el\" href=\"group__artistbrowse.html#ga8dd8364b2fcd29c846209660bd9a69b2\">sp_artistbrowse_create()</a> </td></tr>\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>userdata</em>&nbsp;</td><td>The opaque pointer given to <a class=\"el\" href=\"group__artistbrowse.html#ga8dd8364b2fcd29c846209660bd9a69b2\">sp_artistbrowse_create()</a> </td></tr>\n  </table>\n  </dd>\n</dl>\n\n</div>\n</div>\n<hr/><h2>Function Documentation</h2>\n<a class=\"anchor\" id=\"ga69fc2e1d2d5e8d91a724486cbfd0c4dc\"></a><!-- doxytag: member=\"api.h::sp_artistbrowse_add_ref\" ref=\"ga69fc2e1d2d5e8d91a724486cbfd0c4dc\" args=\"(sp_artistbrowse *arb)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\"><a class=\"el\" href=\"group__error.html#gafd27986ce4cd9eeaeca8adda83c9eb6b\">sp_error</a> sp_artistbrowse_add_ref </td>\n          <td>(</td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__types.html#gafd3d5aae485f1012ec91b7948e6f9f2b\">sp_artistbrowse</a> *&nbsp;</td>\n          <td class=\"paramname\"> <em>arb</em></td>\n          <td>&nbsp;)&nbsp;</td>\n          <td></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Increase the reference count of an artist browse result</p>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>arb</em>&nbsp;</td><td>The artist browse result object </td></tr>\n  </table>\n  </dd>\n</dl>\n<dl class=\"return\"><dt><b>Returns:</b></dt><dd>One of the following errors, from <a class=\"el\" href=\"group__error.html#ga83154178d3a32668658734d2facfa22b\">sp_error</a> SP_ERROR_OK </dd></dl>\n\n</div>\n</div>\n<a class=\"anchor\" id=\"ga5b36c9a34876beea8fda8674b93d4fd3\"></a><!-- doxytag: member=\"api.h::sp_artistbrowse_album\" ref=\"ga5b36c9a34876beea8fda8674b93d4fd3\" args=\"(sp_artistbrowse *arb, int index)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\"><a class=\"el\" href=\"group__types.html#ga6fd3e5de729c429fef3ff18ece6dcfad\">sp_album</a>* sp_artistbrowse_album </td>\n          <td>(</td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__types.html#gafd3d5aae485f1012ec91b7948e6f9f2b\">sp_artistbrowse</a> *&nbsp;</td>\n          <td class=\"paramname\"> <em>arb</em>, </td>\n        </tr>\n        <tr>\n          <td class=\"paramkey\"></td>\n          <td></td>\n          <td class=\"paramtype\">int&nbsp;</td>\n          <td class=\"paramname\"> <em>index</em></td><td>&nbsp;</td>\n        </tr>\n        <tr>\n          <td></td>\n          <td>)</td>\n          <td></td><td></td><td></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Given an artist browse object, return one of its albums</p>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>arb</em>&nbsp;</td><td>Album browse object </td></tr>\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>index</em>&nbsp;</td><td>The index for the album. Should be in the interval [0, <a class=\"el\" href=\"group__artistbrowse.html#gaf0055361abd53425d89a4636a32b5c83\">sp_artistbrowse_num_albums()</a> - 1]</td></tr>\n  </table>\n  </dd>\n</dl>\n<dl class=\"return\"><dt><b>Returns:</b></dt><dd>A album object, or NULL if the index is out of range.</dd></dl>\n<dl class=\"see\"><dt><b>See also:</b></dt><dd><a class=\"el\" href=\"group__album.html\">Album subsystem</a> </dd></dl>\n\n</div>\n</div>\n<a class=\"anchor\" id=\"ga5f6a046b2bd261d7628582b986a9019f\"></a><!-- doxytag: member=\"api.h::sp_artistbrowse_artist\" ref=\"ga5f6a046b2bd261d7628582b986a9019f\" args=\"(sp_artistbrowse *arb)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\"><a class=\"el\" href=\"group__types.html#ga31764fbd69618c10be173c6c03d4c1bc\">sp_artist</a>* sp_artistbrowse_artist </td>\n          <td>(</td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__types.html#gafd3d5aae485f1012ec91b7948e6f9f2b\">sp_artistbrowse</a> *&nbsp;</td>\n          <td class=\"paramname\"> <em>arb</em></td>\n          <td>&nbsp;)&nbsp;</td>\n          <td></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Given an artist browse object, return a pointer to its artist object</p>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>arb</em>&nbsp;</td><td>Artist browse object</td></tr>\n  </table>\n  </dd>\n</dl>\n<dl class=\"return\"><dt><b>Returns:</b></dt><dd>Artist object </dd></dl>\n<dl><dt><b>Examples: </b></dt><dd><a class=\"el\" href=\"browse_8c-example.html#a21\">browse.c</a>.</dd>\n</dl>\n</div>\n</div>\n<a class=\"anchor\" id=\"gadce357748b82abce8a7b093882850fdb\"></a><!-- doxytag: member=\"api.h::sp_artistbrowse_backend_request_duration\" ref=\"gadce357748b82abce8a7b093882850fdb\" args=\"(sp_artistbrowse *arb)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\">int sp_artistbrowse_backend_request_duration </td>\n          <td>(</td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__types.html#gafd3d5aae485f1012ec91b7948e6f9f2b\">sp_artistbrowse</a> *&nbsp;</td>\n          <td class=\"paramname\"> <em>arb</em></td>\n          <td>&nbsp;)&nbsp;</td>\n          <td></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Return the time (in ms) that was spent waiting for the Spotify backend to serve the request</p>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>arb</em>&nbsp;</td><td>Artist browse object</td></tr>\n  </table>\n  </dd>\n</dl>\n<dl class=\"return\"><dt><b>Returns:</b></dt><dd>-1 if the request was served from the local cache If the result is not yet loaded the return value is undefined </dd></dl>\n\n</div>\n</div>\n<a class=\"anchor\" id=\"ga8b93b9e5630662855f35694280ba4d2b\"></a><!-- doxytag: member=\"api.h::sp_artistbrowse_biography\" ref=\"ga8b93b9e5630662855f35694280ba4d2b\" args=\"(sp_artistbrowse *arb)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\">const char* sp_artistbrowse_biography </td>\n          <td>(</td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__types.html#gafd3d5aae485f1012ec91b7948e6f9f2b\">sp_artistbrowse</a> *&nbsp;</td>\n          <td class=\"paramname\"> <em>arb</em></td>\n          <td>&nbsp;)&nbsp;</td>\n          <td></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Given an artist browse object, return the artists biography</p>\n<dl class=\"note\"><dt><b>Note:</b></dt><dd>This function must be called from the same thread that did <a class=\"el\" href=\"group__session.html#gaf2891f2daced4ff6da84219d6376b3aa\">sp_session_create()</a> </dd></dl>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>arb</em>&nbsp;</td><td>Artist browse object</td></tr>\n  </table>\n  </dd>\n</dl>\n<dl class=\"return\"><dt><b>Returns:</b></dt><dd>Biography string in UTF-8 format. Returned string is valid as long as the album object stays allocated and no longer than the next call to <a class=\"el\" href=\"group__session.html#gaff27cb730db6debf55e750e39e7fadd7\">sp_session_process_events()</a> </dd></dl>\n<dl><dt><b>Examples: </b></dt><dd><a class=\"el\" href=\"browse_8c-example.html#a26\">browse.c</a>.</dd>\n</dl>\n</div>\n</div>\n<a class=\"anchor\" id=\"ga8dd8364b2fcd29c846209660bd9a69b2\"></a><!-- doxytag: member=\"api.h::sp_artistbrowse_create\" ref=\"ga8dd8364b2fcd29c846209660bd9a69b2\" args=\"(sp_session *session, sp_artist *artist, sp_artistbrowse_type type, artistbrowse_complete_cb *callback, void *userdata)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\"><a class=\"el\" href=\"group__types.html#gafd3d5aae485f1012ec91b7948e6f9f2b\">sp_artistbrowse</a>* sp_artistbrowse_create </td>\n          <td>(</td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__types.html#ga70dd19c6f824cf6a159575aa4c128b53\">sp_session</a> *&nbsp;</td>\n          <td class=\"paramname\"> <em>session</em>, </td>\n        </tr>\n        <tr>\n          <td class=\"paramkey\"></td>\n          <td></td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__types.html#ga31764fbd69618c10be173c6c03d4c1bc\">sp_artist</a> *&nbsp;</td>\n          <td class=\"paramname\"> <em>artist</em>, </td>\n        </tr>\n        <tr>\n          <td class=\"paramkey\"></td>\n          <td></td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__session.html#gac86504cc9e8cadbc30c8aa8dbf355034\">sp_artistbrowse_type</a>&nbsp;</td>\n          <td class=\"paramname\"> <em>type</em>, </td>\n        </tr>\n        <tr>\n          <td class=\"paramkey\"></td>\n          <td></td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__artistbrowse.html#ga8077aa18c043210e859479be2616a3e7\">artistbrowse_complete_cb</a> *&nbsp;</td>\n          <td class=\"paramname\"> <em>callback</em>, </td>\n        </tr>\n        <tr>\n          <td class=\"paramkey\"></td>\n          <td></td>\n          <td class=\"paramtype\">void *&nbsp;</td>\n          <td class=\"paramname\"> <em>userdata</em></td><td>&nbsp;</td>\n        </tr>\n        <tr>\n          <td></td>\n          <td>)</td>\n          <td></td><td></td><td></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Initiate a request for browsing an artist</p>\n<p>The user is responsible for freeing the returned artist browse using <a class=\"el\" href=\"group__artistbrowse.html#ga14626a4f6a60b1caf61cb54c26783671\">sp_artistbrowse_release()</a>. This can be done in the callback.</p>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>session</em>&nbsp;</td><td>Session object </td></tr>\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>artist</em>&nbsp;</td><td>Artist to be browsed. The artist metadata does not have to be loaded </td></tr>\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>type</em>&nbsp;</td><td>Type of data requested, see the sp_artistbrowse_type enum for details </td></tr>\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>callback</em>&nbsp;</td><td>Callback to be invoked when browsing has been completed. Pass NULL if you are not interested in this event. </td></tr>\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>userdata</em>&nbsp;</td><td>Userdata passed to callback.</td></tr>\n  </table>\n  </dd>\n</dl>\n<dl class=\"return\"><dt><b>Returns:</b></dt><dd>Artist browse object</dd></dl>\n<dl class=\"see\"><dt><b>See also:</b></dt><dd><a class=\"el\" href=\"group__artistbrowse.html#ga8077aa18c043210e859479be2616a3e7\">artistbrowse_complete_cb</a> </dd></dl>\n<dl><dt><b>Examples: </b></dt><dd><a class=\"el\" href=\"browse_8c-example.html#a51\">browse.c</a>.</dd>\n</dl>\n</div>\n</div>\n<a class=\"anchor\" id=\"ga203e757088ff7a5098f16a1367da25d2\"></a><!-- doxytag: member=\"api.h::sp_artistbrowse_error\" ref=\"ga203e757088ff7a5098f16a1367da25d2\" args=\"(sp_artistbrowse *arb)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\"><a class=\"el\" href=\"group__error.html#gafd27986ce4cd9eeaeca8adda83c9eb6b\">sp_error</a> sp_artistbrowse_error </td>\n          <td>(</td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__types.html#gafd3d5aae485f1012ec91b7948e6f9f2b\">sp_artistbrowse</a> *&nbsp;</td>\n          <td class=\"paramname\"> <em>arb</em></td>\n          <td>&nbsp;)&nbsp;</td>\n          <td></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Check if browsing returned an error code.</p>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>arb</em>&nbsp;</td><td>Artist browse object</td></tr>\n  </table>\n  </dd>\n</dl>\n<dl class=\"return\"><dt><b>Returns:</b></dt><dd>One of the following errors, from <a class=\"el\" href=\"group__error.html#ga83154178d3a32668658734d2facfa22b\">sp_error</a> SP_ERROR_OK SP_ERROR_IS_LOADING SP_ERROR_OTHER_PERMANENT SP_ERROR_OTHER_TRANSIENT </dd></dl>\n<dl><dt><b>Examples: </b></dt><dd><a class=\"el\" href=\"browse_8c-example.html#a32\">browse.c</a>.</dd>\n</dl>\n</div>\n</div>\n<a class=\"anchor\" id=\"ga966b0f59e7b2b3d0037e44bb49dcdabc\"></a><!-- doxytag: member=\"api.h::sp_artistbrowse_is_loaded\" ref=\"ga966b0f59e7b2b3d0037e44bb49dcdabc\" args=\"(sp_artistbrowse *arb)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\">bool sp_artistbrowse_is_loaded </td>\n          <td>(</td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__types.html#gafd3d5aae485f1012ec91b7948e6f9f2b\">sp_artistbrowse</a> *&nbsp;</td>\n          <td class=\"paramname\"> <em>arb</em></td>\n          <td>&nbsp;)&nbsp;</td>\n          <td></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Check if an artist browse request is completed</p>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>arb</em>&nbsp;</td><td>Artist browse object</td></tr>\n  </table>\n  </dd>\n</dl>\n<dl class=\"return\"><dt><b>Returns:</b></dt><dd>True if browsing is completed, false if not </dd></dl>\n\n</div>\n</div>\n<a class=\"anchor\" id=\"gaf0055361abd53425d89a4636a32b5c83\"></a><!-- doxytag: member=\"api.h::sp_artistbrowse_num_albums\" ref=\"gaf0055361abd53425d89a4636a32b5c83\" args=\"(sp_artistbrowse *arb)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\">int sp_artistbrowse_num_albums </td>\n          <td>(</td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__types.html#gafd3d5aae485f1012ec91b7948e6f9f2b\">sp_artistbrowse</a> *&nbsp;</td>\n          <td class=\"paramname\"> <em>arb</em></td>\n          <td>&nbsp;)&nbsp;</td>\n          <td></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Given an artist browse object, return number of albums</p>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>arb</em>&nbsp;</td><td>Artist browse object</td></tr>\n  </table>\n  </dd>\n</dl>\n<dl class=\"return\"><dt><b>Returns:</b></dt><dd>Number of albums for given artist </dd></dl>\n\n</div>\n</div>\n<a class=\"anchor\" id=\"ga98dc47d36d2789999bfe62707c5041d7\"></a><!-- doxytag: member=\"api.h::sp_artistbrowse_num_portraits\" ref=\"ga98dc47d36d2789999bfe62707c5041d7\" args=\"(sp_artistbrowse *arb)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\">int sp_artistbrowse_num_portraits </td>\n          <td>(</td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__types.html#gafd3d5aae485f1012ec91b7948e6f9f2b\">sp_artistbrowse</a> *&nbsp;</td>\n          <td class=\"paramname\"> <em>arb</em></td>\n          <td>&nbsp;)&nbsp;</td>\n          <td></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Given an artist browse object, return number of portraits available</p>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>arb</em>&nbsp;</td><td>Artist browse object</td></tr>\n  </table>\n  </dd>\n</dl>\n<dl class=\"return\"><dt><b>Returns:</b></dt><dd>Number of portraits for given artist </dd></dl>\n<dl><dt><b>Examples: </b></dt><dd><a class=\"el\" href=\"browse_8c-example.html#a24\">browse.c</a>.</dd>\n</dl>\n</div>\n</div>\n<a class=\"anchor\" id=\"ga2559638742416ac621af0e919e017d17\"></a><!-- doxytag: member=\"api.h::sp_artistbrowse_num_similar_artists\" ref=\"ga2559638742416ac621af0e919e017d17\" args=\"(sp_artistbrowse *arb)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\">int sp_artistbrowse_num_similar_artists </td>\n          <td>(</td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__types.html#gafd3d5aae485f1012ec91b7948e6f9f2b\">sp_artistbrowse</a> *&nbsp;</td>\n          <td class=\"paramname\"> <em>arb</em></td>\n          <td>&nbsp;)&nbsp;</td>\n          <td></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Given an artist browse object, return number of similar artists</p>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>arb</em>&nbsp;</td><td>Artist browse object</td></tr>\n  </table>\n  </dd>\n</dl>\n<dl class=\"return\"><dt><b>Returns:</b></dt><dd>Number of similar artists for given artist </dd></dl>\n<dl><dt><b>Examples: </b></dt><dd><a class=\"el\" href=\"browse_8c-example.html#a22\">browse.c</a>.</dd>\n</dl>\n</div>\n</div>\n<a class=\"anchor\" id=\"ga0c26782796af954300ce92fddea97637\"></a><!-- doxytag: member=\"api.h::sp_artistbrowse_num_tophit_tracks\" ref=\"ga0c26782796af954300ce92fddea97637\" args=\"(sp_artistbrowse *arb)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\">int sp_artistbrowse_num_tophit_tracks </td>\n          <td>(</td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__types.html#gafd3d5aae485f1012ec91b7948e6f9f2b\">sp_artistbrowse</a> *&nbsp;</td>\n          <td class=\"paramname\"> <em>arb</em></td>\n          <td>&nbsp;)&nbsp;</td>\n          <td></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Given an artist browse object, return number of tophit tracks This is a set of tracks for the artist with highest popularity</p>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>arb</em>&nbsp;</td><td>Artist browse object</td></tr>\n  </table>\n  </dd>\n</dl>\n<dl class=\"return\"><dt><b>Returns:</b></dt><dd>Number of tophit tracks for given artist </dd></dl>\n\n</div>\n</div>\n<a class=\"anchor\" id=\"ga8c862caa2234125ffcc4e93287b1e029\"></a><!-- doxytag: member=\"api.h::sp_artistbrowse_num_tracks\" ref=\"ga8c862caa2234125ffcc4e93287b1e029\" args=\"(sp_artistbrowse *arb)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\">int sp_artistbrowse_num_tracks </td>\n          <td>(</td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__types.html#gafd3d5aae485f1012ec91b7948e6f9f2b\">sp_artistbrowse</a> *&nbsp;</td>\n          <td class=\"paramname\"> <em>arb</em></td>\n          <td>&nbsp;)&nbsp;</td>\n          <td></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Given an artist browse object, return number of tracks</p>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>arb</em>&nbsp;</td><td>Artist browse object</td></tr>\n  </table>\n  </dd>\n</dl>\n<dl class=\"return\"><dt><b>Returns:</b></dt><dd>Number of tracks for given artist </dd></dl>\n<dl><dt><b>Examples: </b></dt><dd><a class=\"el\" href=\"browse_8c-example.html#a25\">browse.c</a>.</dd>\n</dl>\n</div>\n</div>\n<a class=\"anchor\" id=\"ga5f164b2f9609a7bf2c89b3a1407ec239\"></a><!-- doxytag: member=\"api.h::sp_artistbrowse_portrait\" ref=\"ga5f164b2f9609a7bf2c89b3a1407ec239\" args=\"(sp_artistbrowse *arb, int index)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\">const byte* sp_artistbrowse_portrait </td>\n          <td>(</td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__types.html#gafd3d5aae485f1012ec91b7948e6f9f2b\">sp_artistbrowse</a> *&nbsp;</td>\n          <td class=\"paramname\"> <em>arb</em>, </td>\n        </tr>\n        <tr>\n          <td class=\"paramkey\"></td>\n          <td></td>\n          <td class=\"paramtype\">int&nbsp;</td>\n          <td class=\"paramname\"> <em>index</em></td><td>&nbsp;</td>\n        </tr>\n        <tr>\n          <td></td>\n          <td>)</td>\n          <td></td><td></td><td></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Return image ID representing a portrait of the artist</p>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>arb</em>&nbsp;</td><td>Artist object </td></tr>\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>index</em>&nbsp;</td><td>The index of the portrait. Should be in the interval [0, <a class=\"el\" href=\"group__artistbrowse.html#ga98dc47d36d2789999bfe62707c5041d7\">sp_artistbrowse_num_portraits()</a> - 1]</td></tr>\n  </table>\n  </dd>\n</dl>\n<dl class=\"return\"><dt><b>Returns:</b></dt><dd>ID byte sequence that can be passed to <a class=\"el\" href=\"group__image.html#gaf29e89f45945db2b3667bf9db4279c33\">sp_image_create()</a></dd></dl>\n<dl class=\"see\"><dt><b>See also:</b></dt><dd><a class=\"el\" href=\"group__image.html#gaf29e89f45945db2b3667bf9db4279c33\">sp_image_create</a> </dd></dl>\n\n</div>\n</div>\n<a class=\"anchor\" id=\"ga14626a4f6a60b1caf61cb54c26783671\"></a><!-- doxytag: member=\"api.h::sp_artistbrowse_release\" ref=\"ga14626a4f6a60b1caf61cb54c26783671\" args=\"(sp_artistbrowse *arb)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\"><a class=\"el\" href=\"group__error.html#gafd27986ce4cd9eeaeca8adda83c9eb6b\">sp_error</a> sp_artistbrowse_release </td>\n          <td>(</td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__types.html#gafd3d5aae485f1012ec91b7948e6f9f2b\">sp_artistbrowse</a> *&nbsp;</td>\n          <td class=\"paramname\"> <em>arb</em></td>\n          <td>&nbsp;)&nbsp;</td>\n          <td></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Decrease the reference count of an artist browse result</p>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>arb</em>&nbsp;</td><td>The artist browse result object </td></tr>\n  </table>\n  </dd>\n</dl>\n<dl class=\"return\"><dt><b>Returns:</b></dt><dd>One of the following errors, from <a class=\"el\" href=\"group__error.html#ga83154178d3a32668658734d2facfa22b\">sp_error</a> SP_ERROR_OK </dd></dl>\n<dl><dt><b>Examples: </b></dt><dd><a class=\"el\" href=\"browse_8c-example.html#a33\">browse.c</a>.</dd>\n</dl>\n</div>\n</div>\n<a class=\"anchor\" id=\"gac60ef4f9e006a920f1d72b6098743fbc\"></a><!-- doxytag: member=\"api.h::sp_artistbrowse_similar_artist\" ref=\"gac60ef4f9e006a920f1d72b6098743fbc\" args=\"(sp_artistbrowse *arb, int index)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\"><a class=\"el\" href=\"group__types.html#ga31764fbd69618c10be173c6c03d4c1bc\">sp_artist</a>* sp_artistbrowse_similar_artist </td>\n          <td>(</td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__types.html#gafd3d5aae485f1012ec91b7948e6f9f2b\">sp_artistbrowse</a> *&nbsp;</td>\n          <td class=\"paramname\"> <em>arb</em>, </td>\n        </tr>\n        <tr>\n          <td class=\"paramkey\"></td>\n          <td></td>\n          <td class=\"paramtype\">int&nbsp;</td>\n          <td class=\"paramname\"> <em>index</em></td><td>&nbsp;</td>\n        </tr>\n        <tr>\n          <td></td>\n          <td>)</td>\n          <td></td><td></td><td></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Given an artist browse object, return a similar artist by index</p>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>arb</em>&nbsp;</td><td>Album browse object </td></tr>\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>index</em>&nbsp;</td><td>The index for the artist. Should be in the interval [0, <a class=\"el\" href=\"group__artistbrowse.html#ga2559638742416ac621af0e919e017d17\">sp_artistbrowse_num_similar_artists()</a> - 1]</td></tr>\n  </table>\n  </dd>\n</dl>\n<dl class=\"return\"><dt><b>Returns:</b></dt><dd>A pointer to an artist object.</dd></dl>\n<dl class=\"see\"><dt><b>See also:</b></dt><dd><a class=\"el\" href=\"group__artist.html\">Artist subsystem</a> </dd></dl>\n<dl><dt><b>Examples: </b></dt><dd><a class=\"el\" href=\"browse_8c-example.html#a23\">browse.c</a>.</dd>\n</dl>\n</div>\n</div>\n<a class=\"anchor\" id=\"ga5da55f43def03fe9f0d2c8b252b9755a\"></a><!-- doxytag: member=\"api.h::sp_artistbrowse_tophit_track\" ref=\"ga5da55f43def03fe9f0d2c8b252b9755a\" args=\"(sp_artistbrowse *arb, int index)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\"><a class=\"el\" href=\"group__types.html#ga47bbd2262f0c8b5d7147af7d62198e48\">sp_track</a>* sp_artistbrowse_tophit_track </td>\n          <td>(</td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__types.html#gafd3d5aae485f1012ec91b7948e6f9f2b\">sp_artistbrowse</a> *&nbsp;</td>\n          <td class=\"paramname\"> <em>arb</em>, </td>\n        </tr>\n        <tr>\n          <td class=\"paramkey\"></td>\n          <td></td>\n          <td class=\"paramtype\">int&nbsp;</td>\n          <td class=\"paramname\"> <em>index</em></td><td>&nbsp;</td>\n        </tr>\n        <tr>\n          <td></td>\n          <td>)</td>\n          <td></td><td></td><td></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Given an artist browse object, return one of its tophit tracks This is a set of tracks for the artist with highest popularity</p>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>arb</em>&nbsp;</td><td>Album browse object </td></tr>\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>index</em>&nbsp;</td><td>The index for the track. Should be in the interval [0, <a class=\"el\" href=\"group__artistbrowse.html#ga0c26782796af954300ce92fddea97637\">sp_artistbrowse_num_tophit_tracks()</a> - 1]</td></tr>\n  </table>\n  </dd>\n</dl>\n<dl class=\"return\"><dt><b>Returns:</b></dt><dd>A track object, or NULL if the index is out of range.</dd></dl>\n<dl class=\"see\"><dt><b>See also:</b></dt><dd><a class=\"el\" href=\"group__track.html\">Track subsystem</a> </dd></dl>\n\n</div>\n</div>\n<a class=\"anchor\" id=\"ga45d28771a856f935dc40ab40e27dec4c\"></a><!-- doxytag: member=\"api.h::sp_artistbrowse_track\" ref=\"ga45d28771a856f935dc40ab40e27dec4c\" args=\"(sp_artistbrowse *arb, int index)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\"><a class=\"el\" href=\"group__types.html#ga47bbd2262f0c8b5d7147af7d62198e48\">sp_track</a>* sp_artistbrowse_track </td>\n          <td>(</td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__types.html#gafd3d5aae485f1012ec91b7948e6f9f2b\">sp_artistbrowse</a> *&nbsp;</td>\n          <td class=\"paramname\"> <em>arb</em>, </td>\n        </tr>\n        <tr>\n          <td class=\"paramkey\"></td>\n          <td></td>\n          <td class=\"paramtype\">int&nbsp;</td>\n          <td class=\"paramname\"> <em>index</em></td><td>&nbsp;</td>\n        </tr>\n        <tr>\n          <td></td>\n          <td>)</td>\n          <td></td><td></td><td></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Given an artist browse object, return one of its tracks</p>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>arb</em>&nbsp;</td><td>Album browse object </td></tr>\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>index</em>&nbsp;</td><td>The index for the track. Should be in the interval [0, <a class=\"el\" href=\"group__artistbrowse.html#ga8c862caa2234125ffcc4e93287b1e029\">sp_artistbrowse_num_tracks()</a> - 1]</td></tr>\n  </table>\n  </dd>\n</dl>\n<dl class=\"return\"><dt><b>Returns:</b></dt><dd>A track object, or NULL if the index is out of range.</dd></dl>\n<dl class=\"see\"><dt><b>See also:</b></dt><dd><a class=\"el\" href=\"group__track.html\">Track subsystem</a> </dd></dl>\n<dl><dt><b>Examples: </b></dt><dd><a class=\"el\" href=\"browse_8c-example.html#a27\">browse.c</a>.</dd>\n</dl>\n</div>\n</div>\n</div>\n<hr size=\"1\"><address style=\"text-align: right;\"><small>\nGenerated on Wed Jun 13 2012 14:22:40.<br>\nCopyright &copy; 2006&ndash;2012 Spotify Ltd</small></address>\n</body>\n</html>\n"
  },
  {
    "path": "libspotify/docs/html/group__error.html",
    "content": "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\n<html xmlns=\"http://www.w3.org/1999/xhtml\">\n<head>\n<meta http-equiv=\"Content-Type\" content=\"text/xhtml;charset=UTF-8\"/>\n<title>libspotify: Error Handling</title>\n<link href=\"tabs.css\" rel=\"stylesheet\" type=\"text/css\"/>\n<link href=\"doxygen.css\" rel=\"stylesheet\" type=\"text/css\"/>\n</head>\n<body>\n<!-- Generated by Doxygen 1.7.1 -->\n<div class=\"navigation\" id=\"top\">\n  <div class=\"tabs\">\n    <ul class=\"tablist\">\n      <li><a href=\"index.html\"><span>Main&nbsp;Page</span></a></li>\n      <li><a href=\"modules.html\"><span>Modules</span></a></li>\n      <li><a href=\"annotated.html\"><span>Data&nbsp;Structures</span></a></li>\n      <li><a href=\"files.html\"><span>Files</span></a></li>\n      <li><a href=\"examples.html\"><span>Examples</span></a></li>\n    </ul>\n  </div>\n</div>\n<div class=\"header\">\n  <div class=\"summary\">\n<a href=\"#typedef-members\">Typedefs</a> &#124;\n<a href=\"#enum-members\">Enumerations</a> &#124;\n<a href=\"#func-members\">Functions</a>  </div>\n  <div class=\"headertitle\">\n<h1>Error Handling</h1>  </div>\n</div>\n<div class=\"contents\">\n<table class=\"memberdecls\">\n<tr><td colspan=\"2\"><h2><a name=\"typedef-members\"></a>\nTypedefs</h2></td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">typedef enum <a class=\"el\" href=\"group__error.html#gafd27986ce4cd9eeaeca8adda83c9eb6b\">sp_error</a>&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__error.html#ga83154178d3a32668658734d2facfa22b\">sp_error</a></td></tr>\n<tr><td colspan=\"2\"><h2><a name=\"enum-members\"></a>\nEnumerations</h2></td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">enum &nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__error.html#gafd27986ce4cd9eeaeca8adda83c9eb6b\">sp_error</a> { <br/>\n&nbsp;&nbsp;<a class=\"el\" href=\"group__error.html#ggafd27986ce4cd9eeaeca8adda83c9eb6ba16cb277dc84328e4b2c0cf6d5a0c0b8d\">SP_ERROR_OK</a> =  0, \n<br/>\n&nbsp;&nbsp;<a class=\"el\" href=\"group__error.html#ggafd27986ce4cd9eeaeca8adda83c9eb6ba17c588fa9648e3649185e595bdb88d6f\">SP_ERROR_BAD_API_VERSION</a> =  1, \n<br/>\n&nbsp;&nbsp;<a class=\"el\" href=\"group__error.html#ggafd27986ce4cd9eeaeca8adda83c9eb6bac8c438bd52975d14edf23d040e93d114\">SP_ERROR_API_INITIALIZATION_FAILED</a> =  2, \n<br/>\n&nbsp;&nbsp;<a class=\"el\" href=\"group__error.html#ggafd27986ce4cd9eeaeca8adda83c9eb6ba7b94fe2b53f58d91d4c3cda7bb706ff3\">SP_ERROR_TRACK_NOT_PLAYABLE</a> =  3, \n<br/>\n&nbsp;&nbsp;<a class=\"el\" href=\"group__error.html#ggafd27986ce4cd9eeaeca8adda83c9eb6ba2bad808a467ee4418adaa40f4844d059\">SP_ERROR_BAD_APPLICATION_KEY</a> =  5, \n<br/>\n&nbsp;&nbsp;<a class=\"el\" href=\"group__error.html#ggafd27986ce4cd9eeaeca8adda83c9eb6ba41052a4a158fa18bb1b8bfdd8c37f7dc\">SP_ERROR_BAD_USERNAME_OR_PASSWORD</a> =  6, \n<br/>\n&nbsp;&nbsp;<a class=\"el\" href=\"group__error.html#ggafd27986ce4cd9eeaeca8adda83c9eb6ba822f4031a82ab428cd04f2ecdc0e757f\">SP_ERROR_USER_BANNED</a> =  7, \n<br/>\n&nbsp;&nbsp;<a class=\"el\" href=\"group__error.html#ggafd27986ce4cd9eeaeca8adda83c9eb6ba9d11d66176b6ae95bf00486e9e39866b\">SP_ERROR_UNABLE_TO_CONTACT_SERVER</a> =  8, \n<br/>\n&nbsp;&nbsp;<a class=\"el\" href=\"group__error.html#ggafd27986ce4cd9eeaeca8adda83c9eb6ba995344026c012b3f59dc73e12c28b1ba\">SP_ERROR_CLIENT_TOO_OLD</a> =  9, \n<br/>\n&nbsp;&nbsp;<a class=\"el\" href=\"group__error.html#ggafd27986ce4cd9eeaeca8adda83c9eb6ba3f68775a5c001bd1de26afdf5ea4e09d\">SP_ERROR_OTHER_PERMANENT</a> =  10, \n<br/>\n&nbsp;&nbsp;<a class=\"el\" href=\"group__error.html#ggafd27986ce4cd9eeaeca8adda83c9eb6baf3597d4af35adb4fc0d0793ea26f77b4\">SP_ERROR_BAD_USER_AGENT</a> =  11, \n<br/>\n&nbsp;&nbsp;<a class=\"el\" href=\"group__error.html#ggafd27986ce4cd9eeaeca8adda83c9eb6babb1116e69e1d651f9f175dbc8bb5fa32\">SP_ERROR_MISSING_CALLBACK</a> =  12, \n<br/>\n&nbsp;&nbsp;<a class=\"el\" href=\"group__error.html#ggafd27986ce4cd9eeaeca8adda83c9eb6bac9f65a7270391d35342ca9e6c01d519d\">SP_ERROR_INVALID_INDATA</a> =  13, \n<br/>\n&nbsp;&nbsp;<a class=\"el\" href=\"group__error.html#ggafd27986ce4cd9eeaeca8adda83c9eb6ba44b3f132578cbf9a43b5c048efcf63a2\">SP_ERROR_INDEX_OUT_OF_RANGE</a> =  14, \n<br/>\n&nbsp;&nbsp;<a class=\"el\" href=\"group__error.html#ggafd27986ce4cd9eeaeca8adda83c9eb6ba96c08adfcda17005c63142cd4e4cd9bb\">SP_ERROR_USER_NEEDS_PREMIUM</a> =  15, \n<br/>\n&nbsp;&nbsp;<a class=\"el\" href=\"group__error.html#ggafd27986ce4cd9eeaeca8adda83c9eb6baf139c18351a543862bd9393ccebc5f91\">SP_ERROR_OTHER_TRANSIENT</a> =  16, \n<br/>\n&nbsp;&nbsp;<a class=\"el\" href=\"group__error.html#ggafd27986ce4cd9eeaeca8adda83c9eb6ba17f54c30d01baedc24547e62ed417cdd\">SP_ERROR_IS_LOADING</a> =  17, \n<br/>\n&nbsp;&nbsp;<a class=\"el\" href=\"group__error.html#ggafd27986ce4cd9eeaeca8adda83c9eb6ba71307cc7b8460042603f3f322d1096f4\">SP_ERROR_NO_STREAM_AVAILABLE</a> =  18, \n<br/>\n&nbsp;&nbsp;<a class=\"el\" href=\"group__error.html#ggafd27986ce4cd9eeaeca8adda83c9eb6baaddac1f3b82e905711ab9ffe5b4b0329\">SP_ERROR_PERMISSION_DENIED</a> =  19, \n<br/>\n&nbsp;&nbsp;<a class=\"el\" href=\"group__error.html#ggafd27986ce4cd9eeaeca8adda83c9eb6baa4bdf4298c9653549464d21ee528c881\">SP_ERROR_INBOX_IS_FULL</a> =  20, \n<br/>\n&nbsp;&nbsp;<a class=\"el\" href=\"group__error.html#ggafd27986ce4cd9eeaeca8adda83c9eb6ba3b8851ee3ba2bd7ad1fe377d94ac38c0\">SP_ERROR_NO_CACHE</a> =  21, \n<br/>\n&nbsp;&nbsp;<a class=\"el\" href=\"group__error.html#ggafd27986ce4cd9eeaeca8adda83c9eb6baf8ade144869c958de534ecec9f9a36a9\">SP_ERROR_NO_SUCH_USER</a> =  22, \n<br/>\n&nbsp;&nbsp;<a class=\"el\" href=\"group__error.html#ggafd27986ce4cd9eeaeca8adda83c9eb6ba9ad34b997313d790f142f24e77e78e2d\">SP_ERROR_NO_CREDENTIALS</a> =  23, \n<br/>\n&nbsp;&nbsp;<a class=\"el\" href=\"group__error.html#ggafd27986ce4cd9eeaeca8adda83c9eb6ba8fda4dd3ee6ac931337a871fbee02978\">SP_ERROR_NETWORK_DISABLED</a> =  24, \n<br/>\n&nbsp;&nbsp;<a class=\"el\" href=\"group__error.html#ggafd27986ce4cd9eeaeca8adda83c9eb6ba846d94ada9e8db0c2bd5153f5801afa2\">SP_ERROR_INVALID_DEVICE_ID</a> =  25, \n<br/>\n&nbsp;&nbsp;<a class=\"el\" href=\"group__error.html#ggafd27986ce4cd9eeaeca8adda83c9eb6badb3af1736912156cbe0b1e39eaeee1c8\">SP_ERROR_CANT_OPEN_TRACE_FILE</a> =  26, \n<br/>\n&nbsp;&nbsp;<a class=\"el\" href=\"group__error.html#ggafd27986ce4cd9eeaeca8adda83c9eb6ba46c3b6173bb5b09445164402ac5ed81f\">SP_ERROR_APPLICATION_BANNED</a> =  27, \n<br/>\n&nbsp;&nbsp;<a class=\"el\" href=\"group__error.html#ggafd27986ce4cd9eeaeca8adda83c9eb6ba32fd1f63fd4dc7ec50bd11791f02953f\">SP_ERROR_OFFLINE_TOO_MANY_TRACKS</a> =  31, \n<br/>\n&nbsp;&nbsp;<a class=\"el\" href=\"group__error.html#ggafd27986ce4cd9eeaeca8adda83c9eb6bae6b9d9b013f1243548e4fbcf961559ff\">SP_ERROR_OFFLINE_DISK_CACHE</a> =  32, \n<br/>\n&nbsp;&nbsp;<a class=\"el\" href=\"group__error.html#ggafd27986ce4cd9eeaeca8adda83c9eb6ba7e16a1962fd4de081d73dc4a4e32eb04\">SP_ERROR_OFFLINE_EXPIRED</a> =  33, \n<br/>\n&nbsp;&nbsp;<a class=\"el\" href=\"group__error.html#ggafd27986ce4cd9eeaeca8adda83c9eb6bae102b46f4fae3b7b6b34e21ea80d656f\">SP_ERROR_OFFLINE_NOT_ALLOWED</a> =  34, \n<br/>\n&nbsp;&nbsp;<a class=\"el\" href=\"group__error.html#ggafd27986ce4cd9eeaeca8adda83c9eb6ba2c87afb46df21783f172a06b2c25d8f9\">SP_ERROR_OFFLINE_LICENSE_LOST</a> =  35, \n<br/>\n&nbsp;&nbsp;<a class=\"el\" href=\"group__error.html#ggafd27986ce4cd9eeaeca8adda83c9eb6ba9149b343017c0dea431839c8b4d9198c\">SP_ERROR_OFFLINE_LICENSE_ERROR</a> =  36, \n<br/>\n&nbsp;&nbsp;<a class=\"el\" href=\"group__error.html#ggafd27986ce4cd9eeaeca8adda83c9eb6baf588c0f7a2d8d11acea28ac2a4de43c4\">SP_ERROR_LASTFM_AUTH_ERROR</a> =  39, \n<br/>\n&nbsp;&nbsp;<a class=\"el\" href=\"group__error.html#ggafd27986ce4cd9eeaeca8adda83c9eb6ba7f8be4d478e51d2b205157c7c538a3e5\">SP_ERROR_INVALID_ARGUMENT</a> =  40, \n<br/>\n&nbsp;&nbsp;<a class=\"el\" href=\"group__error.html#ggafd27986ce4cd9eeaeca8adda83c9eb6ba73d533e0f25f4ba4cecd6d2e2502b80b\">SP_ERROR_SYSTEM_FAILURE</a> =  41\n<br/>\n }</td></tr>\n<tr><td colspan=\"2\"><h2><a name=\"func-members\"></a>\nFunctions</h2></td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">const char *&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__error.html#ga983dee341d3c2008830513b7cffe7bf3\">sp_error_message</a> (<a class=\"el\" href=\"group__error.html#gafd27986ce4cd9eeaeca8adda83c9eb6b\">sp_error</a> error)</td></tr>\n</table>\n<hr/><a name=\"_details\"></a><h2>Detailed Description</h2>\n<p>All functions in libspotify use the same set of error codes. Most of them return an error code, and let the result of the operation be stored in an out-parameter. </p>\n<hr/><h2>Typedef Documentation</h2>\n<a class=\"anchor\" id=\"ga83154178d3a32668658734d2facfa22b\"></a><!-- doxytag: member=\"api.h::sp_error\" ref=\"ga83154178d3a32668658734d2facfa22b\" args=\"\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\">typedef enum <a class=\"el\" href=\"group__error.html#gafd27986ce4cd9eeaeca8adda83c9eb6b\">sp_error</a>  <a class=\"el\" href=\"group__error.html#gafd27986ce4cd9eeaeca8adda83c9eb6b\">sp_error</a></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Error codes returned by various functions </p>\n\n</div>\n</div>\n<hr/><h2>Enumeration Type Documentation</h2>\n<a class=\"anchor\" id=\"gafd27986ce4cd9eeaeca8adda83c9eb6b\"></a><!-- doxytag: member=\"api.h::sp_error\" ref=\"gafd27986ce4cd9eeaeca8adda83c9eb6b\" args=\"\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\">enum <a class=\"el\" href=\"group__error.html#gafd27986ce4cd9eeaeca8adda83c9eb6b\">sp_error</a></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Error codes returned by various functions </p>\n<dl><dt><b>Enumerator: </b></dt><dd><table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n<tr><td valign=\"top\"><em><a class=\"anchor\" id=\"ggafd27986ce4cd9eeaeca8adda83c9eb6ba16cb277dc84328e4b2c0cf6d5a0c0b8d\"></a><!-- doxytag: member=\"SP_ERROR_OK\" ref=\"ggafd27986ce4cd9eeaeca8adda83c9eb6ba16cb277dc84328e4b2c0cf6d5a0c0b8d\" args=\"\" -->SP_ERROR_OK</em>&nbsp;</td><td>\n<p>No errors encountered. </p>\n</td></tr>\n<tr><td valign=\"top\"><em><a class=\"anchor\" id=\"ggafd27986ce4cd9eeaeca8adda83c9eb6ba17c588fa9648e3649185e595bdb88d6f\"></a><!-- doxytag: member=\"SP_ERROR_BAD_API_VERSION\" ref=\"ggafd27986ce4cd9eeaeca8adda83c9eb6ba17c588fa9648e3649185e595bdb88d6f\" args=\"\" -->SP_ERROR_BAD_API_VERSION</em>&nbsp;</td><td>\n<p>The library version targeted does not match the one you claim you support. </p>\n</td></tr>\n<tr><td valign=\"top\"><em><a class=\"anchor\" id=\"ggafd27986ce4cd9eeaeca8adda83c9eb6bac8c438bd52975d14edf23d040e93d114\"></a><!-- doxytag: member=\"SP_ERROR_API_INITIALIZATION_FAILED\" ref=\"ggafd27986ce4cd9eeaeca8adda83c9eb6bac8c438bd52975d14edf23d040e93d114\" args=\"\" -->SP_ERROR_API_INITIALIZATION_FAILED</em>&nbsp;</td><td>\n<p>Initialization of library failed - are cache locations etc. valid? </p>\n</td></tr>\n<tr><td valign=\"top\"><em><a class=\"anchor\" id=\"ggafd27986ce4cd9eeaeca8adda83c9eb6ba7b94fe2b53f58d91d4c3cda7bb706ff3\"></a><!-- doxytag: member=\"SP_ERROR_TRACK_NOT_PLAYABLE\" ref=\"ggafd27986ce4cd9eeaeca8adda83c9eb6ba7b94fe2b53f58d91d4c3cda7bb706ff3\" args=\"\" -->SP_ERROR_TRACK_NOT_PLAYABLE</em>&nbsp;</td><td>\n<p>The track specified for playing cannot be played. </p>\n</td></tr>\n<tr><td valign=\"top\"><em><a class=\"anchor\" id=\"ggafd27986ce4cd9eeaeca8adda83c9eb6ba2bad808a467ee4418adaa40f4844d059\"></a><!-- doxytag: member=\"SP_ERROR_BAD_APPLICATION_KEY\" ref=\"ggafd27986ce4cd9eeaeca8adda83c9eb6ba2bad808a467ee4418adaa40f4844d059\" args=\"\" -->SP_ERROR_BAD_APPLICATION_KEY</em>&nbsp;</td><td>\n<p>The application key is invalid. </p>\n</td></tr>\n<tr><td valign=\"top\"><em><a class=\"anchor\" id=\"ggafd27986ce4cd9eeaeca8adda83c9eb6ba41052a4a158fa18bb1b8bfdd8c37f7dc\"></a><!-- doxytag: member=\"SP_ERROR_BAD_USERNAME_OR_PASSWORD\" ref=\"ggafd27986ce4cd9eeaeca8adda83c9eb6ba41052a4a158fa18bb1b8bfdd8c37f7dc\" args=\"\" -->SP_ERROR_BAD_USERNAME_OR_PASSWORD</em>&nbsp;</td><td>\n<p>Login failed because of bad username and/or password. </p>\n</td></tr>\n<tr><td valign=\"top\"><em><a class=\"anchor\" id=\"ggafd27986ce4cd9eeaeca8adda83c9eb6ba822f4031a82ab428cd04f2ecdc0e757f\"></a><!-- doxytag: member=\"SP_ERROR_USER_BANNED\" ref=\"ggafd27986ce4cd9eeaeca8adda83c9eb6ba822f4031a82ab428cd04f2ecdc0e757f\" args=\"\" -->SP_ERROR_USER_BANNED</em>&nbsp;</td><td>\n<p>The specified username is banned. </p>\n</td></tr>\n<tr><td valign=\"top\"><em><a class=\"anchor\" id=\"ggafd27986ce4cd9eeaeca8adda83c9eb6ba9d11d66176b6ae95bf00486e9e39866b\"></a><!-- doxytag: member=\"SP_ERROR_UNABLE_TO_CONTACT_SERVER\" ref=\"ggafd27986ce4cd9eeaeca8adda83c9eb6ba9d11d66176b6ae95bf00486e9e39866b\" args=\"\" -->SP_ERROR_UNABLE_TO_CONTACT_SERVER</em>&nbsp;</td><td>\n<p>Cannot connect to the Spotify backend system. </p>\n</td></tr>\n<tr><td valign=\"top\"><em><a class=\"anchor\" id=\"ggafd27986ce4cd9eeaeca8adda83c9eb6ba995344026c012b3f59dc73e12c28b1ba\"></a><!-- doxytag: member=\"SP_ERROR_CLIENT_TOO_OLD\" ref=\"ggafd27986ce4cd9eeaeca8adda83c9eb6ba995344026c012b3f59dc73e12c28b1ba\" args=\"\" -->SP_ERROR_CLIENT_TOO_OLD</em>&nbsp;</td><td>\n<p>Client is too old, library will need to be updated. </p>\n</td></tr>\n<tr><td valign=\"top\"><em><a class=\"anchor\" id=\"ggafd27986ce4cd9eeaeca8adda83c9eb6ba3f68775a5c001bd1de26afdf5ea4e09d\"></a><!-- doxytag: member=\"SP_ERROR_OTHER_PERMANENT\" ref=\"ggafd27986ce4cd9eeaeca8adda83c9eb6ba3f68775a5c001bd1de26afdf5ea4e09d\" args=\"\" -->SP_ERROR_OTHER_PERMANENT</em>&nbsp;</td><td>\n<p>Some other error occurred, and it is permanent (e.g. trying to relogin will not help). </p>\n</td></tr>\n<tr><td valign=\"top\"><em><a class=\"anchor\" id=\"ggafd27986ce4cd9eeaeca8adda83c9eb6baf3597d4af35adb4fc0d0793ea26f77b4\"></a><!-- doxytag: member=\"SP_ERROR_BAD_USER_AGENT\" ref=\"ggafd27986ce4cd9eeaeca8adda83c9eb6baf3597d4af35adb4fc0d0793ea26f77b4\" args=\"\" -->SP_ERROR_BAD_USER_AGENT</em>&nbsp;</td><td>\n<p>The user agent string is invalid or too long. </p>\n</td></tr>\n<tr><td valign=\"top\"><em><a class=\"anchor\" id=\"ggafd27986ce4cd9eeaeca8adda83c9eb6babb1116e69e1d651f9f175dbc8bb5fa32\"></a><!-- doxytag: member=\"SP_ERROR_MISSING_CALLBACK\" ref=\"ggafd27986ce4cd9eeaeca8adda83c9eb6babb1116e69e1d651f9f175dbc8bb5fa32\" args=\"\" -->SP_ERROR_MISSING_CALLBACK</em>&nbsp;</td><td>\n<p>No valid callback registered to handle events. </p>\n</td></tr>\n<tr><td valign=\"top\"><em><a class=\"anchor\" id=\"ggafd27986ce4cd9eeaeca8adda83c9eb6bac9f65a7270391d35342ca9e6c01d519d\"></a><!-- doxytag: member=\"SP_ERROR_INVALID_INDATA\" ref=\"ggafd27986ce4cd9eeaeca8adda83c9eb6bac9f65a7270391d35342ca9e6c01d519d\" args=\"\" -->SP_ERROR_INVALID_INDATA</em>&nbsp;</td><td>\n<p>Input data was either missing or invalid. </p>\n</td></tr>\n<tr><td valign=\"top\"><em><a class=\"anchor\" id=\"ggafd27986ce4cd9eeaeca8adda83c9eb6ba44b3f132578cbf9a43b5c048efcf63a2\"></a><!-- doxytag: member=\"SP_ERROR_INDEX_OUT_OF_RANGE\" ref=\"ggafd27986ce4cd9eeaeca8adda83c9eb6ba44b3f132578cbf9a43b5c048efcf63a2\" args=\"\" -->SP_ERROR_INDEX_OUT_OF_RANGE</em>&nbsp;</td><td>\n<p>Index out of range. </p>\n</td></tr>\n<tr><td valign=\"top\"><em><a class=\"anchor\" id=\"ggafd27986ce4cd9eeaeca8adda83c9eb6ba96c08adfcda17005c63142cd4e4cd9bb\"></a><!-- doxytag: member=\"SP_ERROR_USER_NEEDS_PREMIUM\" ref=\"ggafd27986ce4cd9eeaeca8adda83c9eb6ba96c08adfcda17005c63142cd4e4cd9bb\" args=\"\" -->SP_ERROR_USER_NEEDS_PREMIUM</em>&nbsp;</td><td>\n<p>The specified user needs a premium account. </p>\n</td></tr>\n<tr><td valign=\"top\"><em><a class=\"anchor\" id=\"ggafd27986ce4cd9eeaeca8adda83c9eb6baf139c18351a543862bd9393ccebc5f91\"></a><!-- doxytag: member=\"SP_ERROR_OTHER_TRANSIENT\" ref=\"ggafd27986ce4cd9eeaeca8adda83c9eb6baf139c18351a543862bd9393ccebc5f91\" args=\"\" -->SP_ERROR_OTHER_TRANSIENT</em>&nbsp;</td><td>\n<p>A transient error occurred. </p>\n</td></tr>\n<tr><td valign=\"top\"><em><a class=\"anchor\" id=\"ggafd27986ce4cd9eeaeca8adda83c9eb6ba17f54c30d01baedc24547e62ed417cdd\"></a><!-- doxytag: member=\"SP_ERROR_IS_LOADING\" ref=\"ggafd27986ce4cd9eeaeca8adda83c9eb6ba17f54c30d01baedc24547e62ed417cdd\" args=\"\" -->SP_ERROR_IS_LOADING</em>&nbsp;</td><td>\n<p>The resource is currently loading. </p>\n</td></tr>\n<tr><td valign=\"top\"><em><a class=\"anchor\" id=\"ggafd27986ce4cd9eeaeca8adda83c9eb6ba71307cc7b8460042603f3f322d1096f4\"></a><!-- doxytag: member=\"SP_ERROR_NO_STREAM_AVAILABLE\" ref=\"ggafd27986ce4cd9eeaeca8adda83c9eb6ba71307cc7b8460042603f3f322d1096f4\" args=\"\" -->SP_ERROR_NO_STREAM_AVAILABLE</em>&nbsp;</td><td>\n<p>Could not find any suitable stream to play. </p>\n</td></tr>\n<tr><td valign=\"top\"><em><a class=\"anchor\" id=\"ggafd27986ce4cd9eeaeca8adda83c9eb6baaddac1f3b82e905711ab9ffe5b4b0329\"></a><!-- doxytag: member=\"SP_ERROR_PERMISSION_DENIED\" ref=\"ggafd27986ce4cd9eeaeca8adda83c9eb6baaddac1f3b82e905711ab9ffe5b4b0329\" args=\"\" -->SP_ERROR_PERMISSION_DENIED</em>&nbsp;</td><td>\n<p>Requested operation is not allowed. </p>\n</td></tr>\n<tr><td valign=\"top\"><em><a class=\"anchor\" id=\"ggafd27986ce4cd9eeaeca8adda83c9eb6baa4bdf4298c9653549464d21ee528c881\"></a><!-- doxytag: member=\"SP_ERROR_INBOX_IS_FULL\" ref=\"ggafd27986ce4cd9eeaeca8adda83c9eb6baa4bdf4298c9653549464d21ee528c881\" args=\"\" -->SP_ERROR_INBOX_IS_FULL</em>&nbsp;</td><td>\n<p>Target inbox is full. </p>\n</td></tr>\n<tr><td valign=\"top\"><em><a class=\"anchor\" id=\"ggafd27986ce4cd9eeaeca8adda83c9eb6ba3b8851ee3ba2bd7ad1fe377d94ac38c0\"></a><!-- doxytag: member=\"SP_ERROR_NO_CACHE\" ref=\"ggafd27986ce4cd9eeaeca8adda83c9eb6ba3b8851ee3ba2bd7ad1fe377d94ac38c0\" args=\"\" -->SP_ERROR_NO_CACHE</em>&nbsp;</td><td>\n<p>Cache is not enabled. </p>\n</td></tr>\n<tr><td valign=\"top\"><em><a class=\"anchor\" id=\"ggafd27986ce4cd9eeaeca8adda83c9eb6baf8ade144869c958de534ecec9f9a36a9\"></a><!-- doxytag: member=\"SP_ERROR_NO_SUCH_USER\" ref=\"ggafd27986ce4cd9eeaeca8adda83c9eb6baf8ade144869c958de534ecec9f9a36a9\" args=\"\" -->SP_ERROR_NO_SUCH_USER</em>&nbsp;</td><td>\n<p>Requested user does not exist. </p>\n</td></tr>\n<tr><td valign=\"top\"><em><a class=\"anchor\" id=\"ggafd27986ce4cd9eeaeca8adda83c9eb6ba9ad34b997313d790f142f24e77e78e2d\"></a><!-- doxytag: member=\"SP_ERROR_NO_CREDENTIALS\" ref=\"ggafd27986ce4cd9eeaeca8adda83c9eb6ba9ad34b997313d790f142f24e77e78e2d\" args=\"\" -->SP_ERROR_NO_CREDENTIALS</em>&nbsp;</td><td>\n<p>No credentials are stored. </p>\n</td></tr>\n<tr><td valign=\"top\"><em><a class=\"anchor\" id=\"ggafd27986ce4cd9eeaeca8adda83c9eb6ba8fda4dd3ee6ac931337a871fbee02978\"></a><!-- doxytag: member=\"SP_ERROR_NETWORK_DISABLED\" ref=\"ggafd27986ce4cd9eeaeca8adda83c9eb6ba8fda4dd3ee6ac931337a871fbee02978\" args=\"\" -->SP_ERROR_NETWORK_DISABLED</em>&nbsp;</td><td>\n<p>Network disabled. </p>\n</td></tr>\n<tr><td valign=\"top\"><em><a class=\"anchor\" id=\"ggafd27986ce4cd9eeaeca8adda83c9eb6ba846d94ada9e8db0c2bd5153f5801afa2\"></a><!-- doxytag: member=\"SP_ERROR_INVALID_DEVICE_ID\" ref=\"ggafd27986ce4cd9eeaeca8adda83c9eb6ba846d94ada9e8db0c2bd5153f5801afa2\" args=\"\" -->SP_ERROR_INVALID_DEVICE_ID</em>&nbsp;</td><td>\n<p>Invalid device ID. </p>\n</td></tr>\n<tr><td valign=\"top\"><em><a class=\"anchor\" id=\"ggafd27986ce4cd9eeaeca8adda83c9eb6badb3af1736912156cbe0b1e39eaeee1c8\"></a><!-- doxytag: member=\"SP_ERROR_CANT_OPEN_TRACE_FILE\" ref=\"ggafd27986ce4cd9eeaeca8adda83c9eb6badb3af1736912156cbe0b1e39eaeee1c8\" args=\"\" -->SP_ERROR_CANT_OPEN_TRACE_FILE</em>&nbsp;</td><td>\n<p>Unable to open trace file. </p>\n</td></tr>\n<tr><td valign=\"top\"><em><a class=\"anchor\" id=\"ggafd27986ce4cd9eeaeca8adda83c9eb6ba46c3b6173bb5b09445164402ac5ed81f\"></a><!-- doxytag: member=\"SP_ERROR_APPLICATION_BANNED\" ref=\"ggafd27986ce4cd9eeaeca8adda83c9eb6ba46c3b6173bb5b09445164402ac5ed81f\" args=\"\" -->SP_ERROR_APPLICATION_BANNED</em>&nbsp;</td><td>\n<p>This application is no longer allowed to use the Spotify service. </p>\n</td></tr>\n<tr><td valign=\"top\"><em><a class=\"anchor\" id=\"ggafd27986ce4cd9eeaeca8adda83c9eb6ba32fd1f63fd4dc7ec50bd11791f02953f\"></a><!-- doxytag: member=\"SP_ERROR_OFFLINE_TOO_MANY_TRACKS\" ref=\"ggafd27986ce4cd9eeaeca8adda83c9eb6ba32fd1f63fd4dc7ec50bd11791f02953f\" args=\"\" -->SP_ERROR_OFFLINE_TOO_MANY_TRACKS</em>&nbsp;</td><td>\n<p>Reached the device limit for number of tracks to download. </p>\n</td></tr>\n<tr><td valign=\"top\"><em><a class=\"anchor\" id=\"ggafd27986ce4cd9eeaeca8adda83c9eb6bae6b9d9b013f1243548e4fbcf961559ff\"></a><!-- doxytag: member=\"SP_ERROR_OFFLINE_DISK_CACHE\" ref=\"ggafd27986ce4cd9eeaeca8adda83c9eb6bae6b9d9b013f1243548e4fbcf961559ff\" args=\"\" -->SP_ERROR_OFFLINE_DISK_CACHE</em>&nbsp;</td><td>\n<p>Disk cache is full so no more tracks can be downloaded to offline mode. </p>\n</td></tr>\n<tr><td valign=\"top\"><em><a class=\"anchor\" id=\"ggafd27986ce4cd9eeaeca8adda83c9eb6ba7e16a1962fd4de081d73dc4a4e32eb04\"></a><!-- doxytag: member=\"SP_ERROR_OFFLINE_EXPIRED\" ref=\"ggafd27986ce4cd9eeaeca8adda83c9eb6ba7e16a1962fd4de081d73dc4a4e32eb04\" args=\"\" -->SP_ERROR_OFFLINE_EXPIRED</em>&nbsp;</td><td>\n<p>Offline key has expired, the user needs to go online again. </p>\n</td></tr>\n<tr><td valign=\"top\"><em><a class=\"anchor\" id=\"ggafd27986ce4cd9eeaeca8adda83c9eb6bae102b46f4fae3b7b6b34e21ea80d656f\"></a><!-- doxytag: member=\"SP_ERROR_OFFLINE_NOT_ALLOWED\" ref=\"ggafd27986ce4cd9eeaeca8adda83c9eb6bae102b46f4fae3b7b6b34e21ea80d656f\" args=\"\" -->SP_ERROR_OFFLINE_NOT_ALLOWED</em>&nbsp;</td><td>\n<p>This user is not allowed to use offline mode. </p>\n</td></tr>\n<tr><td valign=\"top\"><em><a class=\"anchor\" id=\"ggafd27986ce4cd9eeaeca8adda83c9eb6ba2c87afb46df21783f172a06b2c25d8f9\"></a><!-- doxytag: member=\"SP_ERROR_OFFLINE_LICENSE_LOST\" ref=\"ggafd27986ce4cd9eeaeca8adda83c9eb6ba2c87afb46df21783f172a06b2c25d8f9\" args=\"\" -->SP_ERROR_OFFLINE_LICENSE_LOST</em>&nbsp;</td><td>\n<p>The license for this device has been lost. Most likely because the user used offline on three other device. </p>\n</td></tr>\n<tr><td valign=\"top\"><em><a class=\"anchor\" id=\"ggafd27986ce4cd9eeaeca8adda83c9eb6ba9149b343017c0dea431839c8b4d9198c\"></a><!-- doxytag: member=\"SP_ERROR_OFFLINE_LICENSE_ERROR\" ref=\"ggafd27986ce4cd9eeaeca8adda83c9eb6ba9149b343017c0dea431839c8b4d9198c\" args=\"\" -->SP_ERROR_OFFLINE_LICENSE_ERROR</em>&nbsp;</td><td>\n<p>The Spotify license server does not respond correctly. </p>\n</td></tr>\n<tr><td valign=\"top\"><em><a class=\"anchor\" id=\"ggafd27986ce4cd9eeaeca8adda83c9eb6baf588c0f7a2d8d11acea28ac2a4de43c4\"></a><!-- doxytag: member=\"SP_ERROR_LASTFM_AUTH_ERROR\" ref=\"ggafd27986ce4cd9eeaeca8adda83c9eb6baf588c0f7a2d8d11acea28ac2a4de43c4\" args=\"\" -->SP_ERROR_LASTFM_AUTH_ERROR</em>&nbsp;</td><td>\n<p>A LastFM scrobble authentication error has occurred. </p>\n</td></tr>\n<tr><td valign=\"top\"><em><a class=\"anchor\" id=\"ggafd27986ce4cd9eeaeca8adda83c9eb6ba7f8be4d478e51d2b205157c7c538a3e5\"></a><!-- doxytag: member=\"SP_ERROR_INVALID_ARGUMENT\" ref=\"ggafd27986ce4cd9eeaeca8adda83c9eb6ba7f8be4d478e51d2b205157c7c538a3e5\" args=\"\" -->SP_ERROR_INVALID_ARGUMENT</em>&nbsp;</td><td>\n<p>An invalid argument was specified. </p>\n</td></tr>\n<tr><td valign=\"top\"><em><a class=\"anchor\" id=\"ggafd27986ce4cd9eeaeca8adda83c9eb6ba73d533e0f25f4ba4cecd6d2e2502b80b\"></a><!-- doxytag: member=\"SP_ERROR_SYSTEM_FAILURE\" ref=\"ggafd27986ce4cd9eeaeca8adda83c9eb6ba73d533e0f25f4ba4cecd6d2e2502b80b\" args=\"\" -->SP_ERROR_SYSTEM_FAILURE</em>&nbsp;</td><td>\n<p>An operating system error. </p>\n</td></tr>\n</table>\n</dd>\n</dl>\n\n</div>\n</div>\n<hr/><h2>Function Documentation</h2>\n<a class=\"anchor\" id=\"ga983dee341d3c2008830513b7cffe7bf3\"></a><!-- doxytag: member=\"api.h::sp_error_message\" ref=\"ga983dee341d3c2008830513b7cffe7bf3\" args=\"(sp_error error)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\">const char* sp_error_message </td>\n          <td>(</td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__error.html#gafd27986ce4cd9eeaeca8adda83c9eb6b\">sp_error</a>&nbsp;</td>\n          <td class=\"paramname\"> <em>error</em></td>\n          <td>&nbsp;)&nbsp;</td>\n          <td></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Convert a numeric libspotify error code to a text string. The error message is in English. This function is useful for logging purposes.</p>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>error</em>&nbsp;</td><td>The error code to lookup </td></tr>\n  </table>\n  </dd>\n</dl>\n<dl><dt><b>Examples: </b></dt><dd><a class=\"el\" href=\"browse_8c-example.html#a30\">browse.c</a>, <a class=\"el\" href=\"jukebox_8c-example.html#a15\">jukebox.c</a>, and <a class=\"el\" href=\"search_8c-example.html#a16\">search.c</a>.</dd>\n</dl>\n</div>\n</div>\n</div>\n<hr size=\"1\"><address style=\"text-align: right;\"><small>\nGenerated on Wed Jun 13 2012 14:22:40.<br>\nCopyright &copy; 2006&ndash;2012 Spotify Ltd</small></address>\n</body>\n</html>\n"
  },
  {
    "path": "libspotify/docs/html/group__image.html",
    "content": "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\n<html xmlns=\"http://www.w3.org/1999/xhtml\">\n<head>\n<meta http-equiv=\"Content-Type\" content=\"text/xhtml;charset=UTF-8\"/>\n<title>libspotify: Image handling</title>\n<link href=\"tabs.css\" rel=\"stylesheet\" type=\"text/css\"/>\n<link href=\"doxygen.css\" rel=\"stylesheet\" type=\"text/css\"/>\n</head>\n<body>\n<!-- Generated by Doxygen 1.7.1 -->\n<div class=\"navigation\" id=\"top\">\n  <div class=\"tabs\">\n    <ul class=\"tablist\">\n      <li><a href=\"index.html\"><span>Main&nbsp;Page</span></a></li>\n      <li><a href=\"modules.html\"><span>Modules</span></a></li>\n      <li><a href=\"annotated.html\"><span>Data&nbsp;Structures</span></a></li>\n      <li><a href=\"files.html\"><span>Files</span></a></li>\n      <li><a href=\"examples.html\"><span>Examples</span></a></li>\n    </ul>\n  </div>\n</div>\n<div class=\"header\">\n  <div class=\"summary\">\n<a href=\"#typedef-members\">Typedefs</a> &#124;\n<a href=\"#enum-members\">Enumerations</a> &#124;\n<a href=\"#func-members\">Functions</a>  </div>\n  <div class=\"headertitle\">\n<h1>Image handling</h1>  </div>\n</div>\n<div class=\"contents\">\n<table class=\"memberdecls\">\n<tr><td colspan=\"2\"><h2><a name=\"typedef-members\"></a>\nTypedefs</h2></td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">typedef void&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__image.html#ga713bef7c5dedba7d91b9710cd9b5faa4\">image_loaded_cb</a> (<a class=\"el\" href=\"group__types.html#ga61155ca7b1ba941e15490e417441917b\">sp_image</a> *image, void *userdata)</td></tr>\n<tr><td colspan=\"2\"><h2><a name=\"enum-members\"></a>\nEnumerations</h2></td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">enum &nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__image.html#ga2cda19baf2460da5e81fb1917f54626b\">sp_imageformat</a> { <br/>\n&nbsp;&nbsp;<a class=\"el\" href=\"group__image.html#gga2cda19baf2460da5e81fb1917f54626ba2fec8a1b400bd6cd5396b9852e4279b6\">SP_IMAGE_FORMAT_UNKNOWN</a> =  -1, \n<br/>\n&nbsp;&nbsp;<a class=\"el\" href=\"group__image.html#gga2cda19baf2460da5e81fb1917f54626ba6263674800bea702c4d913d4b07c135d\">SP_IMAGE_FORMAT_JPEG</a> =  0\n<br/>\n }</td></tr>\n<tr><td colspan=\"2\"><h2><a name=\"func-members\"></a>\nFunctions</h2></td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__types.html#ga61155ca7b1ba941e15490e417441917b\">sp_image</a> *&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__image.html#gaf29e89f45945db2b3667bf9db4279c33\">sp_image_create</a> (<a class=\"el\" href=\"group__types.html#ga70dd19c6f824cf6a159575aa4c128b53\">sp_session</a> *session, const byte image_id[20])</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__types.html#ga61155ca7b1ba941e15490e417441917b\">sp_image</a> *&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__image.html#ga70fb25cd2b0caaf15f637f36e75524b9\">sp_image_create_from_link</a> (<a class=\"el\" href=\"group__types.html#ga70dd19c6f824cf6a159575aa4c128b53\">sp_session</a> *session, <a class=\"el\" href=\"group__types.html#gaf90a23d6b662c96d52ac19f7f4bc1e39\">sp_link</a> *l)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__error.html#gafd27986ce4cd9eeaeca8adda83c9eb6b\">sp_error</a>&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__image.html#gaa414f26ad1b9095645a83361597c92ce\">sp_image_add_load_callback</a> (<a class=\"el\" href=\"group__types.html#ga61155ca7b1ba941e15490e417441917b\">sp_image</a> *image, <a class=\"el\" href=\"group__image.html#ga713bef7c5dedba7d91b9710cd9b5faa4\">image_loaded_cb</a> *callback, void *userdata)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__error.html#gafd27986ce4cd9eeaeca8adda83c9eb6b\">sp_error</a>&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__image.html#gaaee68c65d9eab3499f2b6be5d048d6ba\">sp_image_remove_load_callback</a> (<a class=\"el\" href=\"group__types.html#ga61155ca7b1ba941e15490e417441917b\">sp_image</a> *image, <a class=\"el\" href=\"group__image.html#ga713bef7c5dedba7d91b9710cd9b5faa4\">image_loaded_cb</a> *callback, void *userdata)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">bool&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__image.html#ga45312b1b9b5e5565485d61a8f0300e18\">sp_image_is_loaded</a> (<a class=\"el\" href=\"group__types.html#ga61155ca7b1ba941e15490e417441917b\">sp_image</a> *image)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__error.html#gafd27986ce4cd9eeaeca8adda83c9eb6b\">sp_error</a>&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__image.html#gae40103df87426b346e0d0413d8d3b0ff\">sp_image_error</a> (<a class=\"el\" href=\"group__types.html#ga61155ca7b1ba941e15490e417441917b\">sp_image</a> *image)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__image.html#ga2cda19baf2460da5e81fb1917f54626b\">sp_imageformat</a>&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__image.html#ga04448e81ca4916ba7ed223d0d817e803\">sp_image_format</a> (<a class=\"el\" href=\"group__types.html#ga61155ca7b1ba941e15490e417441917b\">sp_image</a> *image)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">const void *&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__image.html#ga03700a7dfa90bfc8200b89f15acd91aa\">sp_image_data</a> (<a class=\"el\" href=\"group__types.html#ga61155ca7b1ba941e15490e417441917b\">sp_image</a> *image, size_t *data_size)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">const byte *&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__image.html#ga0ee0b98cc25c995fe208a992cc87d145\">sp_image_image_id</a> (<a class=\"el\" href=\"group__types.html#ga61155ca7b1ba941e15490e417441917b\">sp_image</a> *image)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__error.html#gafd27986ce4cd9eeaeca8adda83c9eb6b\">sp_error</a>&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__image.html#ga98c93dbedfb182243742131a5224b83b\">sp_image_add_ref</a> (<a class=\"el\" href=\"group__types.html#ga61155ca7b1ba941e15490e417441917b\">sp_image</a> *image)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__error.html#gafd27986ce4cd9eeaeca8adda83c9eb6b\">sp_error</a>&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__image.html#ga3df9af5f68b18df5a598b7510e9b587f\">sp_image_release</a> (<a class=\"el\" href=\"group__types.html#ga61155ca7b1ba941e15490e417441917b\">sp_image</a> *image)</td></tr>\n</table>\n<hr/><h2>Typedef Documentation</h2>\n<a class=\"anchor\" id=\"ga713bef7c5dedba7d91b9710cd9b5faa4\"></a><!-- doxytag: member=\"api.h::image_loaded_cb\" ref=\"ga713bef7c5dedba7d91b9710cd9b5faa4\" args=\"(sp_image *image, void *userdata)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\">typedef void <a class=\"el\" href=\"group__image.html#ga713bef7c5dedba7d91b9710cd9b5faa4\">image_loaded_cb</a>(<a class=\"el\" href=\"group__types.html#ga61155ca7b1ba941e15490e417441917b\">sp_image</a> *image, void *userdata)</td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>The type of a callback used to notify the application that an image is done loading. </p>\n\n</div>\n</div>\n<hr/><h2>Enumeration Type Documentation</h2>\n<a class=\"anchor\" id=\"ga2cda19baf2460da5e81fb1917f54626b\"></a><!-- doxytag: member=\"api.h::sp_imageformat\" ref=\"ga2cda19baf2460da5e81fb1917f54626b\" args=\"\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\">enum <a class=\"el\" href=\"group__image.html#ga2cda19baf2460da5e81fb1917f54626b\">sp_imageformat</a></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Image format </p>\n<dl><dt><b>Enumerator: </b></dt><dd><table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n<tr><td valign=\"top\"><em><a class=\"anchor\" id=\"gga2cda19baf2460da5e81fb1917f54626ba2fec8a1b400bd6cd5396b9852e4279b6\"></a><!-- doxytag: member=\"SP_IMAGE_FORMAT_UNKNOWN\" ref=\"gga2cda19baf2460da5e81fb1917f54626ba2fec8a1b400bd6cd5396b9852e4279b6\" args=\"\" -->SP_IMAGE_FORMAT_UNKNOWN</em>&nbsp;</td><td>\n<p>Unknown image format. </p>\n</td></tr>\n<tr><td valign=\"top\"><em><a class=\"anchor\" id=\"gga2cda19baf2460da5e81fb1917f54626ba6263674800bea702c4d913d4b07c135d\"></a><!-- doxytag: member=\"SP_IMAGE_FORMAT_JPEG\" ref=\"gga2cda19baf2460da5e81fb1917f54626ba6263674800bea702c4d913d4b07c135d\" args=\"\" -->SP_IMAGE_FORMAT_JPEG</em>&nbsp;</td><td>\n<p>JPEG image. </p>\n</td></tr>\n</table>\n</dd>\n</dl>\n\n</div>\n</div>\n<hr/><h2>Function Documentation</h2>\n<a class=\"anchor\" id=\"gaa414f26ad1b9095645a83361597c92ce\"></a><!-- doxytag: member=\"api.h::sp_image_add_load_callback\" ref=\"gaa414f26ad1b9095645a83361597c92ce\" args=\"(sp_image *image, image_loaded_cb *callback, void *userdata)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\"><a class=\"el\" href=\"group__error.html#gafd27986ce4cd9eeaeca8adda83c9eb6b\">sp_error</a> sp_image_add_load_callback </td>\n          <td>(</td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__types.html#ga61155ca7b1ba941e15490e417441917b\">sp_image</a> *&nbsp;</td>\n          <td class=\"paramname\"> <em>image</em>, </td>\n        </tr>\n        <tr>\n          <td class=\"paramkey\"></td>\n          <td></td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__image.html#ga713bef7c5dedba7d91b9710cd9b5faa4\">image_loaded_cb</a> *&nbsp;</td>\n          <td class=\"paramname\"> <em>callback</em>, </td>\n        </tr>\n        <tr>\n          <td class=\"paramkey\"></td>\n          <td></td>\n          <td class=\"paramtype\">void *&nbsp;</td>\n          <td class=\"paramname\"> <em>userdata</em></td><td>&nbsp;</td>\n        </tr>\n        <tr>\n          <td></td>\n          <td>)</td>\n          <td></td><td></td><td></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Add a callback that will be invoked when the image is loaded</p>\n<p>If an image is loaded, and loading fails, the image will behave like an empty image.</p>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>image</em>&nbsp;</td><td>Image object </td></tr>\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>callback</em>&nbsp;</td><td>Callback that will be called when image has been fetched. </td></tr>\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>userdata</em>&nbsp;</td><td>Opaque pointer passed to <code>callback</code> </td></tr>\n  </table>\n  </dd>\n</dl>\n\n</div>\n</div>\n<a class=\"anchor\" id=\"ga98c93dbedfb182243742131a5224b83b\"></a><!-- doxytag: member=\"api.h::sp_image_add_ref\" ref=\"ga98c93dbedfb182243742131a5224b83b\" args=\"(sp_image *image)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\"><a class=\"el\" href=\"group__error.html#gafd27986ce4cd9eeaeca8adda83c9eb6b\">sp_error</a> sp_image_add_ref </td>\n          <td>(</td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__types.html#ga61155ca7b1ba941e15490e417441917b\">sp_image</a> *&nbsp;</td>\n          <td class=\"paramname\"> <em>image</em></td>\n          <td>&nbsp;)&nbsp;</td>\n          <td></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Increase the reference count of an image</p>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>image</em>&nbsp;</td><td>The image object </td></tr>\n  </table>\n  </dd>\n</dl>\n<dl class=\"return\"><dt><b>Returns:</b></dt><dd>One of the following errors, from <a class=\"el\" href=\"group__error.html#ga83154178d3a32668658734d2facfa22b\">sp_error</a> SP_ERROR_OK </dd></dl>\n\n</div>\n</div>\n<a class=\"anchor\" id=\"gaf29e89f45945db2b3667bf9db4279c33\"></a><!-- doxytag: member=\"api.h::sp_image_create\" ref=\"gaf29e89f45945db2b3667bf9db4279c33\" args=\"(sp_session *session, const byte image_id[20])\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\"><a class=\"el\" href=\"group__types.html#ga61155ca7b1ba941e15490e417441917b\">sp_image</a>* sp_image_create </td>\n          <td>(</td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__types.html#ga70dd19c6f824cf6a159575aa4c128b53\">sp_session</a> *&nbsp;</td>\n          <td class=\"paramname\"> <em>session</em>, </td>\n        </tr>\n        <tr>\n          <td class=\"paramkey\"></td>\n          <td></td>\n          <td class=\"paramtype\">const byte&nbsp;</td>\n          <td class=\"paramname\"> <em>image_id</em>[20]</td><td>&nbsp;</td>\n        </tr>\n        <tr>\n          <td></td>\n          <td>)</td>\n          <td></td><td></td><td></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Create an image object</p>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>session</em>&nbsp;</td><td>Session </td></tr>\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>image_id</em>&nbsp;</td><td>Spotify image ID</td></tr>\n  </table>\n  </dd>\n</dl>\n<dl class=\"return\"><dt><b>Returns:</b></dt><dd>Pointer to an image object. To free the object, use <a class=\"el\" href=\"group__image.html#ga3df9af5f68b18df5a598b7510e9b587f\">sp_image_release()</a></dd></dl>\n<dl class=\"see\"><dt><b>See also:</b></dt><dd><a class=\"el\" href=\"group__album.html#ga6616ef3df724af185c5eb58e8a0fb808\">sp_album_cover</a> </dd>\n<dd>\n<a class=\"el\" href=\"group__artistbrowse.html#ga5f164b2f9609a7bf2c89b3a1407ec239\">sp_artistbrowse_portrait</a> </dd></dl>\n\n</div>\n</div>\n<a class=\"anchor\" id=\"ga70fb25cd2b0caaf15f637f36e75524b9\"></a><!-- doxytag: member=\"api.h::sp_image_create_from_link\" ref=\"ga70fb25cd2b0caaf15f637f36e75524b9\" args=\"(sp_session *session, sp_link *l)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\"><a class=\"el\" href=\"group__types.html#ga61155ca7b1ba941e15490e417441917b\">sp_image</a>* sp_image_create_from_link </td>\n          <td>(</td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__types.html#ga70dd19c6f824cf6a159575aa4c128b53\">sp_session</a> *&nbsp;</td>\n          <td class=\"paramname\"> <em>session</em>, </td>\n        </tr>\n        <tr>\n          <td class=\"paramkey\"></td>\n          <td></td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__types.html#gaf90a23d6b662c96d52ac19f7f4bc1e39\">sp_link</a> *&nbsp;</td>\n          <td class=\"paramname\"> <em>l</em></td><td>&nbsp;</td>\n        </tr>\n        <tr>\n          <td></td>\n          <td>)</td>\n          <td></td><td></td><td></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Create an image object from a link</p>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>session</em>&nbsp;</td><td>Session </td></tr>\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>l</em>&nbsp;</td><td>Spotify link object. This must be of SP_LINKTYPE_IMAGE type</td></tr>\n  </table>\n  </dd>\n</dl>\n<dl class=\"return\"><dt><b>Returns:</b></dt><dd>Pointer to an image object. To free the object, use <a class=\"el\" href=\"group__image.html#ga3df9af5f68b18df5a598b7510e9b587f\">sp_image_release()</a></dd></dl>\n<dl class=\"see\"><dt><b>See also:</b></dt><dd><a class=\"el\" href=\"group__image.html#gaf29e89f45945db2b3667bf9db4279c33\">sp_image_create</a> </dd></dl>\n\n</div>\n</div>\n<a class=\"anchor\" id=\"ga03700a7dfa90bfc8200b89f15acd91aa\"></a><!-- doxytag: member=\"api.h::sp_image_data\" ref=\"ga03700a7dfa90bfc8200b89f15acd91aa\" args=\"(sp_image *image, size_t *data_size)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\">const void* sp_image_data </td>\n          <td>(</td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__types.html#ga61155ca7b1ba941e15490e417441917b\">sp_image</a> *&nbsp;</td>\n          <td class=\"paramname\"> <em>image</em>, </td>\n        </tr>\n        <tr>\n          <td class=\"paramkey\"></td>\n          <td></td>\n          <td class=\"paramtype\">size_t *&nbsp;</td>\n          <td class=\"paramname\"> <em>data_size</em></td><td>&nbsp;</td>\n        </tr>\n        <tr>\n          <td></td>\n          <td>)</td>\n          <td></td><td></td><td></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Get image data</p>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>image</em>&nbsp;</td><td>Image object </td></tr>\n    <tr><td valign=\"top\"><tt>[out]</tt>&nbsp;</td><td valign=\"top\"><em>data_size</em>&nbsp;</td><td>Size of raw image data</td></tr>\n  </table>\n  </dd>\n</dl>\n<dl class=\"return\"><dt><b>Returns:</b></dt><dd>Pointer to raw image data </dd></dl>\n\n</div>\n</div>\n<a class=\"anchor\" id=\"gae40103df87426b346e0d0413d8d3b0ff\"></a><!-- doxytag: member=\"api.h::sp_image_error\" ref=\"gae40103df87426b346e0d0413d8d3b0ff\" args=\"(sp_image *image)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\"><a class=\"el\" href=\"group__error.html#gafd27986ce4cd9eeaeca8adda83c9eb6b\">sp_error</a> sp_image_error </td>\n          <td>(</td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__types.html#ga61155ca7b1ba941e15490e417441917b\">sp_image</a> *&nbsp;</td>\n          <td class=\"paramname\"> <em>image</em></td>\n          <td>&nbsp;)&nbsp;</td>\n          <td></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Check if image retrieval returned an error code.</p>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>image</em>&nbsp;</td><td>Image object</td></tr>\n  </table>\n  </dd>\n</dl>\n<dl class=\"return\"><dt><b>Returns:</b></dt><dd>One of the following errors, from <a class=\"el\" href=\"group__error.html#ga83154178d3a32668658734d2facfa22b\">sp_error</a> SP_ERROR_OK SP_ERROR_IS_LOADING SP_ERROR_OTHER_PERMANENT SP_ERROR_OTHER_TRANSIENT </dd></dl>\n\n</div>\n</div>\n<a class=\"anchor\" id=\"ga04448e81ca4916ba7ed223d0d817e803\"></a><!-- doxytag: member=\"api.h::sp_image_format\" ref=\"ga04448e81ca4916ba7ed223d0d817e803\" args=\"(sp_image *image)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\"><a class=\"el\" href=\"group__image.html#ga2cda19baf2460da5e81fb1917f54626b\">sp_imageformat</a> sp_image_format </td>\n          <td>(</td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__types.html#ga61155ca7b1ba941e15490e417441917b\">sp_image</a> *&nbsp;</td>\n          <td class=\"paramname\"> <em>image</em></td>\n          <td>&nbsp;)&nbsp;</td>\n          <td></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Get image format</p>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>image</em>&nbsp;</td><td>Image object</td></tr>\n  </table>\n  </dd>\n</dl>\n<dl class=\"return\"><dt><b>Returns:</b></dt><dd>Image format as described by sp_imageformat </dd></dl>\n\n</div>\n</div>\n<a class=\"anchor\" id=\"ga0ee0b98cc25c995fe208a992cc87d145\"></a><!-- doxytag: member=\"api.h::sp_image_image_id\" ref=\"ga0ee0b98cc25c995fe208a992cc87d145\" args=\"(sp_image *image)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\">const byte* sp_image_image_id </td>\n          <td>(</td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__types.html#ga61155ca7b1ba941e15490e417441917b\">sp_image</a> *&nbsp;</td>\n          <td class=\"paramname\"> <em>image</em></td>\n          <td>&nbsp;)&nbsp;</td>\n          <td></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Get image ID</p>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>image</em>&nbsp;</td><td>Image object</td></tr>\n  </table>\n  </dd>\n</dl>\n<dl class=\"return\"><dt><b>Returns:</b></dt><dd>Image ID </dd></dl>\n\n</div>\n</div>\n<a class=\"anchor\" id=\"ga45312b1b9b5e5565485d61a8f0300e18\"></a><!-- doxytag: member=\"api.h::sp_image_is_loaded\" ref=\"ga45312b1b9b5e5565485d61a8f0300e18\" args=\"(sp_image *image)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\">bool sp_image_is_loaded </td>\n          <td>(</td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__types.html#ga61155ca7b1ba941e15490e417441917b\">sp_image</a> *&nbsp;</td>\n          <td class=\"paramname\"> <em>image</em></td>\n          <td>&nbsp;)&nbsp;</td>\n          <td></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Check if an image is loaded. Before the image is loaded, the rest of the methods will behave as if the image is empty.</p>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>image</em>&nbsp;</td><td>Image object</td></tr>\n  </table>\n  </dd>\n</dl>\n<dl class=\"return\"><dt><b>Returns:</b></dt><dd>True if image is loaded, false otherwise </dd></dl>\n\n</div>\n</div>\n<a class=\"anchor\" id=\"ga3df9af5f68b18df5a598b7510e9b587f\"></a><!-- doxytag: member=\"api.h::sp_image_release\" ref=\"ga3df9af5f68b18df5a598b7510e9b587f\" args=\"(sp_image *image)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\"><a class=\"el\" href=\"group__error.html#gafd27986ce4cd9eeaeca8adda83c9eb6b\">sp_error</a> sp_image_release </td>\n          <td>(</td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__types.html#ga61155ca7b1ba941e15490e417441917b\">sp_image</a> *&nbsp;</td>\n          <td class=\"paramname\"> <em>image</em></td>\n          <td>&nbsp;)&nbsp;</td>\n          <td></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Decrease the reference count of an image</p>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>image</em>&nbsp;</td><td>The image object </td></tr>\n  </table>\n  </dd>\n</dl>\n<dl class=\"return\"><dt><b>Returns:</b></dt><dd>One of the following errors, from <a class=\"el\" href=\"group__error.html#ga83154178d3a32668658734d2facfa22b\">sp_error</a> SP_ERROR_OK </dd></dl>\n\n</div>\n</div>\n<a class=\"anchor\" id=\"gaaee68c65d9eab3499f2b6be5d048d6ba\"></a><!-- doxytag: member=\"api.h::sp_image_remove_load_callback\" ref=\"gaaee68c65d9eab3499f2b6be5d048d6ba\" args=\"(sp_image *image, image_loaded_cb *callback, void *userdata)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\"><a class=\"el\" href=\"group__error.html#gafd27986ce4cd9eeaeca8adda83c9eb6b\">sp_error</a> sp_image_remove_load_callback </td>\n          <td>(</td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__types.html#ga61155ca7b1ba941e15490e417441917b\">sp_image</a> *&nbsp;</td>\n          <td class=\"paramname\"> <em>image</em>, </td>\n        </tr>\n        <tr>\n          <td class=\"paramkey\"></td>\n          <td></td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__image.html#ga713bef7c5dedba7d91b9710cd9b5faa4\">image_loaded_cb</a> *&nbsp;</td>\n          <td class=\"paramname\"> <em>callback</em>, </td>\n        </tr>\n        <tr>\n          <td class=\"paramkey\"></td>\n          <td></td>\n          <td class=\"paramtype\">void *&nbsp;</td>\n          <td class=\"paramname\"> <em>userdata</em></td><td>&nbsp;</td>\n        </tr>\n        <tr>\n          <td></td>\n          <td>)</td>\n          <td></td><td></td><td></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Remove an image load callback previously added with <a class=\"el\" href=\"group__image.html#gaa414f26ad1b9095645a83361597c92ce\">sp_image_add_load_callback()</a></p>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>image</em>&nbsp;</td><td>Image object </td></tr>\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>callback</em>&nbsp;</td><td>Callback that will not be called when image has been fetched. </td></tr>\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>userdata</em>&nbsp;</td><td>Opaque pointer passed to <code>callback</code> </td></tr>\n  </table>\n  </dd>\n</dl>\n<dl class=\"return\"><dt><b>Returns:</b></dt><dd>One of the following errors, from <a class=\"el\" href=\"group__error.html#ga83154178d3a32668658734d2facfa22b\">sp_error</a> SP_ERROR_OK </dd></dl>\n\n</div>\n</div>\n</div>\n<hr size=\"1\"><address style=\"text-align: right;\"><small>\nGenerated on Wed Jun 13 2012 14:22:40.<br>\nCopyright &copy; 2006&ndash;2012 Spotify Ltd</small></address>\n</body>\n</html>\n"
  },
  {
    "path": "libspotify/docs/html/group__inbox.html",
    "content": "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\n<html xmlns=\"http://www.w3.org/1999/xhtml\">\n<head>\n<meta http-equiv=\"Content-Type\" content=\"text/xhtml;charset=UTF-8\"/>\n<title>libspotify: Inbox subsystem</title>\n<link href=\"tabs.css\" rel=\"stylesheet\" type=\"text/css\"/>\n<link href=\"doxygen.css\" rel=\"stylesheet\" type=\"text/css\"/>\n</head>\n<body>\n<!-- Generated by Doxygen 1.7.1 -->\n<div class=\"navigation\" id=\"top\">\n  <div class=\"tabs\">\n    <ul class=\"tablist\">\n      <li><a href=\"index.html\"><span>Main&nbsp;Page</span></a></li>\n      <li><a href=\"modules.html\"><span>Modules</span></a></li>\n      <li><a href=\"annotated.html\"><span>Data&nbsp;Structures</span></a></li>\n      <li><a href=\"files.html\"><span>Files</span></a></li>\n      <li><a href=\"examples.html\"><span>Examples</span></a></li>\n    </ul>\n  </div>\n</div>\n<div class=\"header\">\n  <div class=\"summary\">\n<a href=\"#typedef-members\">Typedefs</a> &#124;\n<a href=\"#func-members\">Functions</a>  </div>\n  <div class=\"headertitle\">\n<h1>Inbox subsystem</h1>  </div>\n</div>\n<div class=\"contents\">\n<table class=\"memberdecls\">\n<tr><td colspan=\"2\"><h2><a name=\"typedef-members\"></a>\nTypedefs</h2></td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">typedef void&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__inbox.html#ga5084d6ab753294730402a0c43b82e60c\">inboxpost_complete_cb</a> (<a class=\"el\" href=\"group__types.html#gaec0f2e5098cebc05ce56adfc9b346510\">sp_inbox</a> *result, void *userdata)</td></tr>\n<tr><td colspan=\"2\"><h2><a name=\"func-members\"></a>\nFunctions</h2></td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__types.html#gaec0f2e5098cebc05ce56adfc9b346510\">sp_inbox</a> *&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__inbox.html#gaee29e747ca10b36597d91689ae074aa2\">sp_inbox_post_tracks</a> (<a class=\"el\" href=\"group__types.html#ga70dd19c6f824cf6a159575aa4c128b53\">sp_session</a> *session, const char *user, <a class=\"el\" href=\"group__types.html#ga47bbd2262f0c8b5d7147af7d62198e48\">sp_track</a> *const *tracks, int num_tracks, const char *message, <a class=\"el\" href=\"group__inbox.html#ga5084d6ab753294730402a0c43b82e60c\">inboxpost_complete_cb</a> *callback, void *userdata)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__error.html#gafd27986ce4cd9eeaeca8adda83c9eb6b\">sp_error</a>&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__inbox.html#gaa452e9fe1fa7c9e2c780d28ce2ed63c5\">sp_inbox_error</a> (<a class=\"el\" href=\"group__types.html#gaec0f2e5098cebc05ce56adfc9b346510\">sp_inbox</a> *inbox)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__error.html#gafd27986ce4cd9eeaeca8adda83c9eb6b\">sp_error</a>&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__inbox.html#gadb6b607bc26b9d362de4da09ec1c864f\">sp_inbox_add_ref</a> (<a class=\"el\" href=\"group__types.html#gaec0f2e5098cebc05ce56adfc9b346510\">sp_inbox</a> *inbox)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__error.html#gafd27986ce4cd9eeaeca8adda83c9eb6b\">sp_error</a>&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__inbox.html#ga73659a65af92d30e4ac1cf3e06e74a0a\">sp_inbox_release</a> (<a class=\"el\" href=\"group__types.html#gaec0f2e5098cebc05ce56adfc9b346510\">sp_inbox</a> *inbox)</td></tr>\n</table>\n<hr/><h2>Typedef Documentation</h2>\n<a class=\"anchor\" id=\"ga5084d6ab753294730402a0c43b82e60c\"></a><!-- doxytag: member=\"api.h::inboxpost_complete_cb\" ref=\"ga5084d6ab753294730402a0c43b82e60c\" args=\"(sp_inbox *result, void *userdata)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\">typedef void <a class=\"el\" href=\"group__inbox.html#ga5084d6ab753294730402a0c43b82e60c\">inboxpost_complete_cb</a>(<a class=\"el\" href=\"group__types.html#gaec0f2e5098cebc05ce56adfc9b346510\">sp_inbox</a> *result, void *userdata)</td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>The type of a callback used in sp_inbox_post()</p>\n<p>When this callback is called, the <a class=\"el\" href=\"group__track.html#ga8b69cf193679c7e00031ae43e61c6a54\">sp_track_is_loaded()</a>, <a class=\"el\" href=\"group__album.html#ga46fbfa98be12c2f4067d5e679552cfb9\">sp_album_is_loaded()</a>, and <a class=\"el\" href=\"group__artist.html#gafc98f5093184a7ac7ce608302b0971ea\">sp_artist_is_loaded()</a> functions will return non-zero for the objects contained in the search result.</p>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>result</em>&nbsp;</td><td>The same pointer returned by <a class=\"el\" href=\"group__search.html#ga2f64dfbcc1313e7d5179998cb28208d4\">sp_search_create()</a> </td></tr>\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>userdata</em>&nbsp;</td><td>The opaque pointer given to <a class=\"el\" href=\"group__search.html#ga2f64dfbcc1313e7d5179998cb28208d4\">sp_search_create()</a> </td></tr>\n  </table>\n  </dd>\n</dl>\n\n</div>\n</div>\n<hr/><h2>Function Documentation</h2>\n<a class=\"anchor\" id=\"gadb6b607bc26b9d362de4da09ec1c864f\"></a><!-- doxytag: member=\"api.h::sp_inbox_add_ref\" ref=\"gadb6b607bc26b9d362de4da09ec1c864f\" args=\"(sp_inbox *inbox)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\"><a class=\"el\" href=\"group__error.html#gafd27986ce4cd9eeaeca8adda83c9eb6b\">sp_error</a> sp_inbox_add_ref </td>\n          <td>(</td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__types.html#gaec0f2e5098cebc05ce56adfc9b346510\">sp_inbox</a> *&nbsp;</td>\n          <td class=\"paramname\"> <em>inbox</em></td>\n          <td>&nbsp;)&nbsp;</td>\n          <td></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Increase the reference count of a inbox result</p>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>inbox</em>&nbsp;</td><td>The inbox result object </td></tr>\n  </table>\n  </dd>\n</dl>\n<dl class=\"return\"><dt><b>Returns:</b></dt><dd>One of the following errors, from <a class=\"el\" href=\"group__error.html#ga83154178d3a32668658734d2facfa22b\">sp_error</a> SP_ERROR_OK </dd></dl>\n\n</div>\n</div>\n<a class=\"anchor\" id=\"gaa452e9fe1fa7c9e2c780d28ce2ed63c5\"></a><!-- doxytag: member=\"api.h::sp_inbox_error\" ref=\"gaa452e9fe1fa7c9e2c780d28ce2ed63c5\" args=\"(sp_inbox *inbox)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\"><a class=\"el\" href=\"group__error.html#gafd27986ce4cd9eeaeca8adda83c9eb6b\">sp_error</a> sp_inbox_error </td>\n          <td>(</td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__types.html#gaec0f2e5098cebc05ce56adfc9b346510\">sp_inbox</a> *&nbsp;</td>\n          <td class=\"paramname\"> <em>inbox</em></td>\n          <td>&nbsp;)&nbsp;</td>\n          <td></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Check if inbox operation returned an error code.</p>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>inbox</em>&nbsp;</td><td>Inbox object</td></tr>\n  </table>\n  </dd>\n</dl>\n<dl class=\"return\"><dt><b>Returns:</b></dt><dd>One of the following errors, from <a class=\"el\" href=\"group__error.html#ga83154178d3a32668658734d2facfa22b\">sp_error</a> SP_ERROR_OK SP_ERROR_OTHER_TRANSIENT SP_ERROR_PERMISSION_DENIED SP_ERROR_INVALID_INDATA SP_ERROR_INBOX_IS_FULL SP_ERROR_NO_SUCH_USER SP_ERROR_OTHER_PERMANENT </dd></dl>\n\n</div>\n</div>\n<a class=\"anchor\" id=\"gaee29e747ca10b36597d91689ae074aa2\"></a><!-- doxytag: member=\"api.h::sp_inbox_post_tracks\" ref=\"gaee29e747ca10b36597d91689ae074aa2\" args=\"(sp_session *session, const char *user, sp_track *const *tracks, int num_tracks, const char *message, inboxpost_complete_cb *callback, void *userdata)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\"><a class=\"el\" href=\"group__types.html#gaec0f2e5098cebc05ce56adfc9b346510\">sp_inbox</a>* sp_inbox_post_tracks </td>\n          <td>(</td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__types.html#ga70dd19c6f824cf6a159575aa4c128b53\">sp_session</a> *&nbsp;</td>\n          <td class=\"paramname\"> <em>session</em>, </td>\n        </tr>\n        <tr>\n          <td class=\"paramkey\"></td>\n          <td></td>\n          <td class=\"paramtype\">const char *&nbsp;</td>\n          <td class=\"paramname\"> <em>user</em>, </td>\n        </tr>\n        <tr>\n          <td class=\"paramkey\"></td>\n          <td></td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__types.html#ga47bbd2262f0c8b5d7147af7d62198e48\">sp_track</a> *const *&nbsp;</td>\n          <td class=\"paramname\"> <em>tracks</em>, </td>\n        </tr>\n        <tr>\n          <td class=\"paramkey\"></td>\n          <td></td>\n          <td class=\"paramtype\">int&nbsp;</td>\n          <td class=\"paramname\"> <em>num_tracks</em>, </td>\n        </tr>\n        <tr>\n          <td class=\"paramkey\"></td>\n          <td></td>\n          <td class=\"paramtype\">const char *&nbsp;</td>\n          <td class=\"paramname\"> <em>message</em>, </td>\n        </tr>\n        <tr>\n          <td class=\"paramkey\"></td>\n          <td></td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__inbox.html#ga5084d6ab753294730402a0c43b82e60c\">inboxpost_complete_cb</a> *&nbsp;</td>\n          <td class=\"paramname\"> <em>callback</em>, </td>\n        </tr>\n        <tr>\n          <td class=\"paramkey\"></td>\n          <td></td>\n          <td class=\"paramtype\">void *&nbsp;</td>\n          <td class=\"paramname\"> <em>userdata</em></td><td>&nbsp;</td>\n        </tr>\n        <tr>\n          <td></td>\n          <td>)</td>\n          <td></td><td></td><td></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Add to inbox</p>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>session</em>&nbsp;</td><td>Session object </td></tr>\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>user</em>&nbsp;</td><td>Canonical username of recipient </td></tr>\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>tracks</em>&nbsp;</td><td>Array of tracks to post </td></tr>\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>num_tracks</em>&nbsp;</td><td>Number of tracks in <code>tracks</code> </td></tr>\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>message</em>&nbsp;</td><td>Message to attach to tracks. UTF-8 </td></tr>\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>callback</em>&nbsp;</td><td>Callback to be invoked when the request has completed </td></tr>\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>userdata</em>&nbsp;</td><td>Userdata passed to callback</td></tr>\n  </table>\n  </dd>\n</dl>\n<dl class=\"return\"><dt><b>Returns:</b></dt><dd>sp_inbox object if the request has been sent, NULL if request failed to initialize </dd></dl>\n\n</div>\n</div>\n<a class=\"anchor\" id=\"ga73659a65af92d30e4ac1cf3e06e74a0a\"></a><!-- doxytag: member=\"api.h::sp_inbox_release\" ref=\"ga73659a65af92d30e4ac1cf3e06e74a0a\" args=\"(sp_inbox *inbox)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\"><a class=\"el\" href=\"group__error.html#gafd27986ce4cd9eeaeca8adda83c9eb6b\">sp_error</a> sp_inbox_release </td>\n          <td>(</td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__types.html#gaec0f2e5098cebc05ce56adfc9b346510\">sp_inbox</a> *&nbsp;</td>\n          <td class=\"paramname\"> <em>inbox</em></td>\n          <td>&nbsp;)&nbsp;</td>\n          <td></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Decrease the reference count of a inbox result</p>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>inbox</em>&nbsp;</td><td>The inbox result object </td></tr>\n  </table>\n  </dd>\n</dl>\n<dl class=\"return\"><dt><b>Returns:</b></dt><dd>One of the following errors, from <a class=\"el\" href=\"group__error.html#ga83154178d3a32668658734d2facfa22b\">sp_error</a> SP_ERROR_OK </dd></dl>\n\n</div>\n</div>\n</div>\n<hr size=\"1\"><address style=\"text-align: right;\"><small>\nGenerated on Wed Jun 13 2012 14:22:40.<br>\nCopyright &copy; 2006&ndash;2012 Spotify Ltd</small></address>\n</body>\n</html>\n"
  },
  {
    "path": "libspotify/docs/html/group__link.html",
    "content": "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\n<html xmlns=\"http://www.w3.org/1999/xhtml\">\n<head>\n<meta http-equiv=\"Content-Type\" content=\"text/xhtml;charset=UTF-8\"/>\n<title>libspotify: Links (Spotify URIs)</title>\n<link href=\"tabs.css\" rel=\"stylesheet\" type=\"text/css\"/>\n<link href=\"doxygen.css\" rel=\"stylesheet\" type=\"text/css\"/>\n</head>\n<body>\n<!-- Generated by Doxygen 1.7.1 -->\n<div class=\"navigation\" id=\"top\">\n  <div class=\"tabs\">\n    <ul class=\"tablist\">\n      <li><a href=\"index.html\"><span>Main&nbsp;Page</span></a></li>\n      <li><a href=\"modules.html\"><span>Modules</span></a></li>\n      <li><a href=\"annotated.html\"><span>Data&nbsp;Structures</span></a></li>\n      <li><a href=\"files.html\"><span>Files</span></a></li>\n      <li><a href=\"examples.html\"><span>Examples</span></a></li>\n    </ul>\n  </div>\n</div>\n<div class=\"header\">\n  <div class=\"summary\">\n<a href=\"#enum-members\">Enumerations</a> &#124;\n<a href=\"#func-members\">Functions</a>  </div>\n  <div class=\"headertitle\">\n<h1>Links (Spotify URIs)</h1>  </div>\n</div>\n<div class=\"contents\">\n<table class=\"memberdecls\">\n<tr><td colspan=\"2\"><h2><a name=\"enum-members\"></a>\nEnumerations</h2></td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">enum &nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__link.html#gabe9611f04086cdbed6e4e6e1fd913b98\">sp_linktype</a> { <br/>\n&nbsp;&nbsp;<a class=\"el\" href=\"group__link.html#ggabe9611f04086cdbed6e4e6e1fd913b98a88b0098486cde586b4dcffb623ac6e63\">SP_LINKTYPE_INVALID</a> =  0, \n<br/>\n&nbsp;&nbsp;<a class=\"el\" href=\"group__link.html#ggabe9611f04086cdbed6e4e6e1fd913b98a5911dbb7258ed160b2f9c114cef152f1\">SP_LINKTYPE_TRACK</a> =  1, \n<br/>\n&nbsp;&nbsp;<a class=\"el\" href=\"group__link.html#ggabe9611f04086cdbed6e4e6e1fd913b98a7716eb95eed852d08300e6e64febc7f3\">SP_LINKTYPE_ALBUM</a> =  2, \n<br/>\n&nbsp;&nbsp;<a class=\"el\" href=\"group__link.html#ggabe9611f04086cdbed6e4e6e1fd913b98a4402b3b001aebb39fd55296f83c60b7e\">SP_LINKTYPE_ARTIST</a> =  3, \n<br/>\n&nbsp;&nbsp;<a class=\"el\" href=\"group__link.html#ggabe9611f04086cdbed6e4e6e1fd913b98ad5909ab9b1cca702163e116b04b6ee8e\">SP_LINKTYPE_SEARCH</a> =  4, \n<br/>\n&nbsp;&nbsp;<a class=\"el\" href=\"group__link.html#ggabe9611f04086cdbed6e4e6e1fd913b98a2640ed065a64b6a9f67e71bbeb2af2dd\">SP_LINKTYPE_PLAYLIST</a> =  5, \n<br/>\n&nbsp;&nbsp;<a class=\"el\" href=\"group__link.html#ggabe9611f04086cdbed6e4e6e1fd913b98ab7a356adce8b1ea34daf21532c7b50e6\">SP_LINKTYPE_PROFILE</a> =  6, \n<br/>\n&nbsp;&nbsp;<a class=\"el\" href=\"group__link.html#ggabe9611f04086cdbed6e4e6e1fd913b98ab649bd86d0fc55ab3fafed3050261353\">SP_LINKTYPE_STARRED</a> =  7, \n<br/>\n&nbsp;&nbsp;<a class=\"el\" href=\"group__link.html#ggabe9611f04086cdbed6e4e6e1fd913b98a0698cd0123190c7af55daf79bb642805\">SP_LINKTYPE_LOCALTRACK</a> =  8, \n<br/>\n&nbsp;&nbsp;<a class=\"el\" href=\"group__link.html#ggabe9611f04086cdbed6e4e6e1fd913b98a1b20b8e2b8773df47b241dc7d28ea0e8\">SP_LINKTYPE_IMAGE</a> =  9\n<br/>\n }</td></tr>\n<tr><td colspan=\"2\"><h2><a name=\"func-members\"></a>\nFunctions</h2></td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__types.html#gaf90a23d6b662c96d52ac19f7f4bc1e39\">sp_link</a> *&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__link.html#gaea9c39f35f7986fc9fed4584fa211127\">sp_link_create_from_string</a> (const char *link)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__types.html#gaf90a23d6b662c96d52ac19f7f4bc1e39\">sp_link</a> *&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__link.html#ga82c29419ce70e2b504670e3d45167d5d\">sp_link_create_from_track</a> (<a class=\"el\" href=\"group__types.html#ga47bbd2262f0c8b5d7147af7d62198e48\">sp_track</a> *track, int offset)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__types.html#gaf90a23d6b662c96d52ac19f7f4bc1e39\">sp_link</a> *&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__link.html#ga040627b0df84425947c82cd8890122ad\">sp_link_create_from_album</a> (<a class=\"el\" href=\"group__types.html#ga6fd3e5de729c429fef3ff18ece6dcfad\">sp_album</a> *album)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__types.html#gaf90a23d6b662c96d52ac19f7f4bc1e39\">sp_link</a> *&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__link.html#gaa87e346c29f1077d7a62c364719d4a55\">sp_link_create_from_album_cover</a> (<a class=\"el\" href=\"group__types.html#ga6fd3e5de729c429fef3ff18ece6dcfad\">sp_album</a> *album, <a class=\"el\" href=\"group__session.html#ga61bc424465d776af3ceeb69eee2bb492\">sp_image_size</a> size)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__types.html#gaf90a23d6b662c96d52ac19f7f4bc1e39\">sp_link</a> *&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__link.html#ga3196ce9de3da4f1d5944a0b58bd80540\">sp_link_create_from_artist</a> (<a class=\"el\" href=\"group__types.html#ga31764fbd69618c10be173c6c03d4c1bc\">sp_artist</a> *artist)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__types.html#gaf90a23d6b662c96d52ac19f7f4bc1e39\">sp_link</a> *&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__link.html#gaafb25ee14bfb27f9cbbab1b039d4d225\">sp_link_create_from_artist_portrait</a> (<a class=\"el\" href=\"group__types.html#ga31764fbd69618c10be173c6c03d4c1bc\">sp_artist</a> *artist, <a class=\"el\" href=\"group__session.html#ga61bc424465d776af3ceeb69eee2bb492\">sp_image_size</a> size)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__types.html#gaf90a23d6b662c96d52ac19f7f4bc1e39\">sp_link</a> *&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__link.html#ga32218fbd912ddddbb749cb42a72b6bcd\">sp_link_create_from_artistbrowse_portrait</a> (<a class=\"el\" href=\"group__types.html#gafd3d5aae485f1012ec91b7948e6f9f2b\">sp_artistbrowse</a> *arb, int index)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__types.html#gaf90a23d6b662c96d52ac19f7f4bc1e39\">sp_link</a> *&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__link.html#ga95c97ba4de9c4040047276ad618a108e\">sp_link_create_from_search</a> (<a class=\"el\" href=\"group__types.html#gac95893a6b23d4b19f6f149eed6ead1fd\">sp_search</a> *search)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__types.html#gaf90a23d6b662c96d52ac19f7f4bc1e39\">sp_link</a> *&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__link.html#ga805392bfa8e526eebedc1cf5a7bcae0f\">sp_link_create_from_playlist</a> (<a class=\"el\" href=\"group__types.html#ga1bcf54cbc117a20ab2c15e59eb3a8174\">sp_playlist</a> *playlist)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__types.html#gaf90a23d6b662c96d52ac19f7f4bc1e39\">sp_link</a> *&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__link.html#gaaa78b1750179c17f8152408cea43efef\">sp_link_create_from_user</a> (<a class=\"el\" href=\"group__types.html#gaed2dbaa1eebd6752f76613daad9158bc\">sp_user</a> *user)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__types.html#gaf90a23d6b662c96d52ac19f7f4bc1e39\">sp_link</a> *&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__link.html#gaa85fbea312127db44685b7e9dc492042\">sp_link_create_from_image</a> (<a class=\"el\" href=\"group__types.html#ga61155ca7b1ba941e15490e417441917b\">sp_image</a> *image)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">int&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__link.html#ga9f169be53f098adcf12f7a10b8bd3ef7\">sp_link_as_string</a> (<a class=\"el\" href=\"group__types.html#gaf90a23d6b662c96d52ac19f7f4bc1e39\">sp_link</a> *link, char *buffer, int buffer_size)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__link.html#gabe9611f04086cdbed6e4e6e1fd913b98\">sp_linktype</a>&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__link.html#ga6140f924c696d53469bb8930cd53e1e6\">sp_link_type</a> (<a class=\"el\" href=\"group__types.html#gaf90a23d6b662c96d52ac19f7f4bc1e39\">sp_link</a> *link)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__types.html#ga47bbd2262f0c8b5d7147af7d62198e48\">sp_track</a> *&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__link.html#ga2560687997d7ce0fbf4f05251d87d32a\">sp_link_as_track</a> (<a class=\"el\" href=\"group__types.html#gaf90a23d6b662c96d52ac19f7f4bc1e39\">sp_link</a> *link)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__types.html#ga47bbd2262f0c8b5d7147af7d62198e48\">sp_track</a> *&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__link.html#ga80f6f752832f76c268c0bfd3ca45e6d2\">sp_link_as_track_and_offset</a> (<a class=\"el\" href=\"group__types.html#gaf90a23d6b662c96d52ac19f7f4bc1e39\">sp_link</a> *link, int *offset)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__types.html#ga6fd3e5de729c429fef3ff18ece6dcfad\">sp_album</a> *&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__link.html#gaafa98628d0abadcca27dd3b227c7337b\">sp_link_as_album</a> (<a class=\"el\" href=\"group__types.html#gaf90a23d6b662c96d52ac19f7f4bc1e39\">sp_link</a> *link)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__types.html#ga31764fbd69618c10be173c6c03d4c1bc\">sp_artist</a> *&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__link.html#gab32979d26dcf68936202fa7aed7b6e49\">sp_link_as_artist</a> (<a class=\"el\" href=\"group__types.html#gaf90a23d6b662c96d52ac19f7f4bc1e39\">sp_link</a> *link)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__types.html#gaed2dbaa1eebd6752f76613daad9158bc\">sp_user</a> *&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__link.html#ga3e29975f47fc0a51be813b4774a3d6f3\">sp_link_as_user</a> (<a class=\"el\" href=\"group__types.html#gaf90a23d6b662c96d52ac19f7f4bc1e39\">sp_link</a> *link)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__error.html#gafd27986ce4cd9eeaeca8adda83c9eb6b\">sp_error</a>&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__link.html#gac5a808b15bceed41508bd3863c8f4b3b\">sp_link_add_ref</a> (<a class=\"el\" href=\"group__types.html#gaf90a23d6b662c96d52ac19f7f4bc1e39\">sp_link</a> *link)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__error.html#gafd27986ce4cd9eeaeca8adda83c9eb6b\">sp_error</a>&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__link.html#ga2b06ab16d1f6436cd8d36dbff2b5c022\">sp_link_release</a> (<a class=\"el\" href=\"group__types.html#gaf90a23d6b662c96d52ac19f7f4bc1e39\">sp_link</a> *link)</td></tr>\n</table>\n<hr/><a name=\"_details\"></a><h2>Detailed Description</h2>\n<p>These functions handle links to Spotify entities in a way that allows you to not care about the textual representation of the link. </p>\n<hr/><h2>Enumeration Type Documentation</h2>\n<a class=\"anchor\" id=\"gabe9611f04086cdbed6e4e6e1fd913b98\"></a><!-- doxytag: member=\"api.h::sp_linktype\" ref=\"gabe9611f04086cdbed6e4e6e1fd913b98\" args=\"\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\">enum <a class=\"el\" href=\"group__link.html#gabe9611f04086cdbed6e4e6e1fd913b98\">sp_linktype</a></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Link types </p>\n<dl><dt><b>Enumerator: </b></dt><dd><table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n<tr><td valign=\"top\"><em><a class=\"anchor\" id=\"ggabe9611f04086cdbed6e4e6e1fd913b98a88b0098486cde586b4dcffb623ac6e63\"></a><!-- doxytag: member=\"SP_LINKTYPE_INVALID\" ref=\"ggabe9611f04086cdbed6e4e6e1fd913b98a88b0098486cde586b4dcffb623ac6e63\" args=\"\" -->SP_LINKTYPE_INVALID</em>&nbsp;</td><td>\n<p>Link type not valid - default until the library has parsed the link, or when parsing failed. </p>\n</td></tr>\n<tr><td valign=\"top\"><em><a class=\"anchor\" id=\"ggabe9611f04086cdbed6e4e6e1fd913b98a5911dbb7258ed160b2f9c114cef152f1\"></a><!-- doxytag: member=\"SP_LINKTYPE_TRACK\" ref=\"ggabe9611f04086cdbed6e4e6e1fd913b98a5911dbb7258ed160b2f9c114cef152f1\" args=\"\" -->SP_LINKTYPE_TRACK</em>&nbsp;</td><td>\n<p>Link type is track. </p>\n</td></tr>\n<tr><td valign=\"top\"><em><a class=\"anchor\" id=\"ggabe9611f04086cdbed6e4e6e1fd913b98a7716eb95eed852d08300e6e64febc7f3\"></a><!-- doxytag: member=\"SP_LINKTYPE_ALBUM\" ref=\"ggabe9611f04086cdbed6e4e6e1fd913b98a7716eb95eed852d08300e6e64febc7f3\" args=\"\" -->SP_LINKTYPE_ALBUM</em>&nbsp;</td><td>\n<p>Link type is album. </p>\n</td></tr>\n<tr><td valign=\"top\"><em><a class=\"anchor\" id=\"ggabe9611f04086cdbed6e4e6e1fd913b98a4402b3b001aebb39fd55296f83c60b7e\"></a><!-- doxytag: member=\"SP_LINKTYPE_ARTIST\" ref=\"ggabe9611f04086cdbed6e4e6e1fd913b98a4402b3b001aebb39fd55296f83c60b7e\" args=\"\" -->SP_LINKTYPE_ARTIST</em>&nbsp;</td><td>\n<p>Link type is artist. </p>\n</td></tr>\n<tr><td valign=\"top\"><em><a class=\"anchor\" id=\"ggabe9611f04086cdbed6e4e6e1fd913b98ad5909ab9b1cca702163e116b04b6ee8e\"></a><!-- doxytag: member=\"SP_LINKTYPE_SEARCH\" ref=\"ggabe9611f04086cdbed6e4e6e1fd913b98ad5909ab9b1cca702163e116b04b6ee8e\" args=\"\" -->SP_LINKTYPE_SEARCH</em>&nbsp;</td><td>\n<p>Link type is search. </p>\n</td></tr>\n<tr><td valign=\"top\"><em><a class=\"anchor\" id=\"ggabe9611f04086cdbed6e4e6e1fd913b98a2640ed065a64b6a9f67e71bbeb2af2dd\"></a><!-- doxytag: member=\"SP_LINKTYPE_PLAYLIST\" ref=\"ggabe9611f04086cdbed6e4e6e1fd913b98a2640ed065a64b6a9f67e71bbeb2af2dd\" args=\"\" -->SP_LINKTYPE_PLAYLIST</em>&nbsp;</td><td>\n<p>Link type is playlist. </p>\n</td></tr>\n<tr><td valign=\"top\"><em><a class=\"anchor\" id=\"ggabe9611f04086cdbed6e4e6e1fd913b98ab7a356adce8b1ea34daf21532c7b50e6\"></a><!-- doxytag: member=\"SP_LINKTYPE_PROFILE\" ref=\"ggabe9611f04086cdbed6e4e6e1fd913b98ab7a356adce8b1ea34daf21532c7b50e6\" args=\"\" -->SP_LINKTYPE_PROFILE</em>&nbsp;</td><td>\n<p>Link type is profile. </p>\n</td></tr>\n<tr><td valign=\"top\"><em><a class=\"anchor\" id=\"ggabe9611f04086cdbed6e4e6e1fd913b98ab649bd86d0fc55ab3fafed3050261353\"></a><!-- doxytag: member=\"SP_LINKTYPE_STARRED\" ref=\"ggabe9611f04086cdbed6e4e6e1fd913b98ab649bd86d0fc55ab3fafed3050261353\" args=\"\" -->SP_LINKTYPE_STARRED</em>&nbsp;</td><td>\n<p>Link type is starred. </p>\n</td></tr>\n<tr><td valign=\"top\"><em><a class=\"anchor\" id=\"ggabe9611f04086cdbed6e4e6e1fd913b98a0698cd0123190c7af55daf79bb642805\"></a><!-- doxytag: member=\"SP_LINKTYPE_LOCALTRACK\" ref=\"ggabe9611f04086cdbed6e4e6e1fd913b98a0698cd0123190c7af55daf79bb642805\" args=\"\" -->SP_LINKTYPE_LOCALTRACK</em>&nbsp;</td><td>\n<p>Link type is a local file. </p>\n</td></tr>\n<tr><td valign=\"top\"><em><a class=\"anchor\" id=\"ggabe9611f04086cdbed6e4e6e1fd913b98a1b20b8e2b8773df47b241dc7d28ea0e8\"></a><!-- doxytag: member=\"SP_LINKTYPE_IMAGE\" ref=\"ggabe9611f04086cdbed6e4e6e1fd913b98a1b20b8e2b8773df47b241dc7d28ea0e8\" args=\"\" -->SP_LINKTYPE_IMAGE</em>&nbsp;</td><td>\n<p>Link type is an image. </p>\n</td></tr>\n</table>\n</dd>\n</dl>\n\n</div>\n</div>\n<hr/><h2>Function Documentation</h2>\n<a class=\"anchor\" id=\"gac5a808b15bceed41508bd3863c8f4b3b\"></a><!-- doxytag: member=\"api.h::sp_link_add_ref\" ref=\"gac5a808b15bceed41508bd3863c8f4b3b\" args=\"(sp_link *link)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\"><a class=\"el\" href=\"group__error.html#gafd27986ce4cd9eeaeca8adda83c9eb6b\">sp_error</a> sp_link_add_ref </td>\n          <td>(</td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__types.html#gaf90a23d6b662c96d52ac19f7f4bc1e39\">sp_link</a> *&nbsp;</td>\n          <td class=\"paramname\"> <em>link</em></td>\n          <td>&nbsp;)&nbsp;</td>\n          <td></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Increase the reference count of a link</p>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>link</em>&nbsp;</td><td>The link object </td></tr>\n  </table>\n  </dd>\n</dl>\n<dl class=\"return\"><dt><b>Returns:</b></dt><dd>One of the following errors, from <a class=\"el\" href=\"group__error.html#ga83154178d3a32668658734d2facfa22b\">sp_error</a> SP_ERROR_OK </dd></dl>\n\n</div>\n</div>\n<a class=\"anchor\" id=\"gaafa98628d0abadcca27dd3b227c7337b\"></a><!-- doxytag: member=\"api.h::sp_link_as_album\" ref=\"gaafa98628d0abadcca27dd3b227c7337b\" args=\"(sp_link *link)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\"><a class=\"el\" href=\"group__types.html#ga6fd3e5de729c429fef3ff18ece6dcfad\">sp_album</a>* sp_link_as_album </td>\n          <td>(</td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__types.html#gaf90a23d6b662c96d52ac19f7f4bc1e39\">sp_link</a> *&nbsp;</td>\n          <td class=\"paramname\"> <em>link</em></td>\n          <td>&nbsp;)&nbsp;</td>\n          <td></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>The album representation for the given link</p>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>link</em>&nbsp;</td><td>The Spotify link whose album you are interested in</td></tr>\n  </table>\n  </dd>\n</dl>\n<dl class=\"return\"><dt><b>Returns:</b></dt><dd>The album representation of the given album link If the link is not of album type then NULL is returned </dd></dl>\n<dl><dt><b>Examples: </b></dt><dd><a class=\"el\" href=\"browse_8c-example.html#a49\">browse.c</a>.</dd>\n</dl>\n</div>\n</div>\n<a class=\"anchor\" id=\"gab32979d26dcf68936202fa7aed7b6e49\"></a><!-- doxytag: member=\"api.h::sp_link_as_artist\" ref=\"gab32979d26dcf68936202fa7aed7b6e49\" args=\"(sp_link *link)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\"><a class=\"el\" href=\"group__types.html#ga31764fbd69618c10be173c6c03d4c1bc\">sp_artist</a>* sp_link_as_artist </td>\n          <td>(</td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__types.html#gaf90a23d6b662c96d52ac19f7f4bc1e39\">sp_link</a> *&nbsp;</td>\n          <td class=\"paramname\"> <em>link</em></td>\n          <td>&nbsp;)&nbsp;</td>\n          <td></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>The artist representation for the given link</p>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>link</em>&nbsp;</td><td>The Spotify link whose artist you are interested in</td></tr>\n  </table>\n  </dd>\n</dl>\n<dl class=\"return\"><dt><b>Returns:</b></dt><dd>The artist representation of the given link If the link is not of artist type then NULL is returned </dd></dl>\n<dl><dt><b>Examples: </b></dt><dd><a class=\"el\" href=\"browse_8c-example.html#a52\">browse.c</a>.</dd>\n</dl>\n</div>\n</div>\n<a class=\"anchor\" id=\"ga9f169be53f098adcf12f7a10b8bd3ef7\"></a><!-- doxytag: member=\"api.h::sp_link_as_string\" ref=\"ga9f169be53f098adcf12f7a10b8bd3ef7\" args=\"(sp_link *link, char *buffer, int buffer_size)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\">int sp_link_as_string </td>\n          <td>(</td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__types.html#gaf90a23d6b662c96d52ac19f7f4bc1e39\">sp_link</a> *&nbsp;</td>\n          <td class=\"paramname\"> <em>link</em>, </td>\n        </tr>\n        <tr>\n          <td class=\"paramkey\"></td>\n          <td></td>\n          <td class=\"paramtype\">char *&nbsp;</td>\n          <td class=\"paramname\"> <em>buffer</em>, </td>\n        </tr>\n        <tr>\n          <td class=\"paramkey\"></td>\n          <td></td>\n          <td class=\"paramtype\">int&nbsp;</td>\n          <td class=\"paramname\"> <em>buffer_size</em></td><td>&nbsp;</td>\n        </tr>\n        <tr>\n          <td></td>\n          <td>)</td>\n          <td></td><td></td><td></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Create a string representation of the given Spotify link</p>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>link</em>&nbsp;</td><td>The Spotify link whose string representation you are interested in </td></tr>\n    <tr><td valign=\"top\"><tt>[out]</tt>&nbsp;</td><td valign=\"top\"><em>buffer</em>&nbsp;</td><td>The buffer to hold the string representation of link </td></tr>\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>buffer_size</em>&nbsp;</td><td>The max size of the buffer that will hold the string representation The resulting string is guaranteed to always be null terminated if buffer_size &gt; 0</td></tr>\n  </table>\n  </dd>\n</dl>\n<dl class=\"return\"><dt><b>Returns:</b></dt><dd>The number of characters in the string representation of the link. If this value is greater or equal than <code>buffer_size</code>, output was truncated. </dd></dl>\n<dl><dt><b>Examples: </b></dt><dd><a class=\"el\" href=\"browse_8c-example.html#a11\">browse.c</a>, and <a class=\"el\" href=\"toplist_8c-example.html#a5\">toplist.c</a>.</dd>\n</dl>\n</div>\n</div>\n<a class=\"anchor\" id=\"ga2560687997d7ce0fbf4f05251d87d32a\"></a><!-- doxytag: member=\"api.h::sp_link_as_track\" ref=\"ga2560687997d7ce0fbf4f05251d87d32a\" args=\"(sp_link *link)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\"><a class=\"el\" href=\"group__types.html#ga47bbd2262f0c8b5d7147af7d62198e48\">sp_track</a>* sp_link_as_track </td>\n          <td>(</td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__types.html#gaf90a23d6b662c96d52ac19f7f4bc1e39\">sp_link</a> *&nbsp;</td>\n          <td class=\"paramname\"> <em>link</em></td>\n          <td>&nbsp;)&nbsp;</td>\n          <td></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>The track representation for the given link</p>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>link</em>&nbsp;</td><td>The Spotify link whose track you are interested in</td></tr>\n  </table>\n  </dd>\n</dl>\n<dl class=\"return\"><dt><b>Returns:</b></dt><dd>The track representation of the given track link If the link is not of track type then NULL is returned. </dd></dl>\n<dl><dt><b>Examples: </b></dt><dd><a class=\"el\" href=\"browse_8c-example.html#a56\">browse.c</a>.</dd>\n</dl>\n</div>\n</div>\n<a class=\"anchor\" id=\"ga80f6f752832f76c268c0bfd3ca45e6d2\"></a><!-- doxytag: member=\"api.h::sp_link_as_track_and_offset\" ref=\"ga80f6f752832f76c268c0bfd3ca45e6d2\" args=\"(sp_link *link, int *offset)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\"><a class=\"el\" href=\"group__types.html#ga47bbd2262f0c8b5d7147af7d62198e48\">sp_track</a>* sp_link_as_track_and_offset </td>\n          <td>(</td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__types.html#gaf90a23d6b662c96d52ac19f7f4bc1e39\">sp_link</a> *&nbsp;</td>\n          <td class=\"paramname\"> <em>link</em>, </td>\n        </tr>\n        <tr>\n          <td class=\"paramkey\"></td>\n          <td></td>\n          <td class=\"paramtype\">int *&nbsp;</td>\n          <td class=\"paramname\"> <em>offset</em></td><td>&nbsp;</td>\n        </tr>\n        <tr>\n          <td></td>\n          <td>)</td>\n          <td></td><td></td><td></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>The track and offset into track representation for the given link</p>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>link</em>&nbsp;</td><td>The Spotify link whose track you are interested in </td></tr>\n    <tr><td valign=\"top\"><tt>[out]</tt>&nbsp;</td><td valign=\"top\"><em>offset</em>&nbsp;</td><td>Pointer to offset into track (in milliseconds). If the link does not contain an offset this will be set to 0.</td></tr>\n  </table>\n  </dd>\n</dl>\n<dl class=\"return\"><dt><b>Returns:</b></dt><dd>The track representation of the given track link If the link is not of track type then NULL is returned. </dd></dl>\n\n</div>\n</div>\n<a class=\"anchor\" id=\"ga3e29975f47fc0a51be813b4774a3d6f3\"></a><!-- doxytag: member=\"api.h::sp_link_as_user\" ref=\"ga3e29975f47fc0a51be813b4774a3d6f3\" args=\"(sp_link *link)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\"><a class=\"el\" href=\"group__types.html#gaed2dbaa1eebd6752f76613daad9158bc\">sp_user</a>* sp_link_as_user </td>\n          <td>(</td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__types.html#gaf90a23d6b662c96d52ac19f7f4bc1e39\">sp_link</a> *&nbsp;</td>\n          <td class=\"paramname\"> <em>link</em></td>\n          <td>&nbsp;)&nbsp;</td>\n          <td></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>The user representation for the given link</p>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>link</em>&nbsp;</td><td>The Spotify link whose user you are interested in</td></tr>\n  </table>\n  </dd>\n</dl>\n<dl class=\"return\"><dt><b>Returns:</b></dt><dd>The user representation of the given link If the link is not of user type then NULL is returned </dd></dl>\n\n</div>\n</div>\n<a class=\"anchor\" id=\"ga040627b0df84425947c82cd8890122ad\"></a><!-- doxytag: member=\"api.h::sp_link_create_from_album\" ref=\"ga040627b0df84425947c82cd8890122ad\" args=\"(sp_album *album)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\"><a class=\"el\" href=\"group__types.html#gaf90a23d6b662c96d52ac19f7f4bc1e39\">sp_link</a>* sp_link_create_from_album </td>\n          <td>(</td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__types.html#ga6fd3e5de729c429fef3ff18ece6dcfad\">sp_album</a> *&nbsp;</td>\n          <td class=\"paramname\"> <em>album</em></td>\n          <td>&nbsp;)&nbsp;</td>\n          <td></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Create a link object from an album</p>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>album</em>&nbsp;</td><td>An album object</td></tr>\n  </table>\n  </dd>\n</dl>\n<dl class=\"return\"><dt><b>Returns:</b></dt><dd>A link representing the album</dd></dl>\n<dl class=\"note\"><dt><b>Note:</b></dt><dd>You need to release the link when you are done with it. </dd></dl>\n<dl class=\"see\"><dt><b>See also:</b></dt><dd><a class=\"el\" href=\"group__link.html#ga2b06ab16d1f6436cd8d36dbff2b5c022\">sp_link_release()</a> </dd></dl>\n\n</div>\n</div>\n<a class=\"anchor\" id=\"gaa87e346c29f1077d7a62c364719d4a55\"></a><!-- doxytag: member=\"api.h::sp_link_create_from_album_cover\" ref=\"gaa87e346c29f1077d7a62c364719d4a55\" args=\"(sp_album *album, sp_image_size size)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\"><a class=\"el\" href=\"group__types.html#gaf90a23d6b662c96d52ac19f7f4bc1e39\">sp_link</a>* sp_link_create_from_album_cover </td>\n          <td>(</td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__types.html#ga6fd3e5de729c429fef3ff18ece6dcfad\">sp_album</a> *&nbsp;</td>\n          <td class=\"paramname\"> <em>album</em>, </td>\n        </tr>\n        <tr>\n          <td class=\"paramkey\"></td>\n          <td></td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__session.html#ga61bc424465d776af3ceeb69eee2bb492\">sp_image_size</a>&nbsp;</td>\n          <td class=\"paramname\"> <em>size</em></td><td>&nbsp;</td>\n        </tr>\n        <tr>\n          <td></td>\n          <td>)</td>\n          <td></td><td></td><td></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Create an image link object from an album</p>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>album</em>&nbsp;</td><td>An album object </td></tr>\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>size</em>&nbsp;</td><td>The desired size of the image</td></tr>\n  </table>\n  </dd>\n</dl>\n<dl class=\"return\"><dt><b>Returns:</b></dt><dd>A link representing the album cover. Type is set to SP_LINKTYPE_IMAGE</dd></dl>\n<dl class=\"note\"><dt><b>Note:</b></dt><dd>You need to release the link when you are done with it. </dd></dl>\n<dl class=\"see\"><dt><b>See also:</b></dt><dd><a class=\"el\" href=\"group__link.html#ga2b06ab16d1f6436cd8d36dbff2b5c022\">sp_link_release()</a> </dd></dl>\n\n</div>\n</div>\n<a class=\"anchor\" id=\"ga3196ce9de3da4f1d5944a0b58bd80540\"></a><!-- doxytag: member=\"api.h::sp_link_create_from_artist\" ref=\"ga3196ce9de3da4f1d5944a0b58bd80540\" args=\"(sp_artist *artist)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\"><a class=\"el\" href=\"group__types.html#gaf90a23d6b662c96d52ac19f7f4bc1e39\">sp_link</a>* sp_link_create_from_artist </td>\n          <td>(</td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__types.html#ga31764fbd69618c10be173c6c03d4c1bc\">sp_artist</a> *&nbsp;</td>\n          <td class=\"paramname\"> <em>artist</em></td>\n          <td>&nbsp;)&nbsp;</td>\n          <td></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Creates a link object from an artist</p>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>artist</em>&nbsp;</td><td>An artist object</td></tr>\n  </table>\n  </dd>\n</dl>\n<dl class=\"return\"><dt><b>Returns:</b></dt><dd>A link object representing the artist</dd></dl>\n<dl class=\"note\"><dt><b>Note:</b></dt><dd>You need to release the link when you are done with it. </dd></dl>\n<dl class=\"see\"><dt><b>See also:</b></dt><dd><a class=\"el\" href=\"group__link.html#ga2b06ab16d1f6436cd8d36dbff2b5c022\">sp_link_release()</a> </dd></dl>\n\n</div>\n</div>\n<a class=\"anchor\" id=\"gaafb25ee14bfb27f9cbbab1b039d4d225\"></a><!-- doxytag: member=\"api.h::sp_link_create_from_artist_portrait\" ref=\"gaafb25ee14bfb27f9cbbab1b039d4d225\" args=\"(sp_artist *artist, sp_image_size size)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\"><a class=\"el\" href=\"group__types.html#gaf90a23d6b662c96d52ac19f7f4bc1e39\">sp_link</a>* sp_link_create_from_artist_portrait </td>\n          <td>(</td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__types.html#ga31764fbd69618c10be173c6c03d4c1bc\">sp_artist</a> *&nbsp;</td>\n          <td class=\"paramname\"> <em>artist</em>, </td>\n        </tr>\n        <tr>\n          <td class=\"paramkey\"></td>\n          <td></td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__session.html#ga61bc424465d776af3ceeb69eee2bb492\">sp_image_size</a>&nbsp;</td>\n          <td class=\"paramname\"> <em>size</em></td><td>&nbsp;</td>\n        </tr>\n        <tr>\n          <td></td>\n          <td>)</td>\n          <td></td><td></td><td></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Creates a link object pointing to an artist portrait</p>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>artist</em>&nbsp;</td><td>Artist browse object </td></tr>\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>size</em>&nbsp;</td><td>The desired size of the image</td></tr>\n  </table>\n  </dd>\n</dl>\n<dl class=\"return\"><dt><b>Returns:</b></dt><dd>A link object representing an image</dd></dl>\n<dl class=\"note\"><dt><b>Note:</b></dt><dd>You need to release the link when you are done with it. </dd></dl>\n<dl class=\"see\"><dt><b>See also:</b></dt><dd><a class=\"el\" href=\"group__link.html#ga2b06ab16d1f6436cd8d36dbff2b5c022\">sp_link_release()</a> </dd>\n<dd>\n<a class=\"el\" href=\"group__artistbrowse.html#ga98dc47d36d2789999bfe62707c5041d7\">sp_artistbrowse_num_portraits()</a> </dd></dl>\n<dl><dt><b>Examples: </b></dt><dd><a class=\"el\" href=\"toplist_8c-example.html#a3\">toplist.c</a>.</dd>\n</dl>\n</div>\n</div>\n<a class=\"anchor\" id=\"ga32218fbd912ddddbb749cb42a72b6bcd\"></a><!-- doxytag: member=\"api.h::sp_link_create_from_artistbrowse_portrait\" ref=\"ga32218fbd912ddddbb749cb42a72b6bcd\" args=\"(sp_artistbrowse *arb, int index)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\"><a class=\"el\" href=\"group__types.html#gaf90a23d6b662c96d52ac19f7f4bc1e39\">sp_link</a>* sp_link_create_from_artistbrowse_portrait </td>\n          <td>(</td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__types.html#gafd3d5aae485f1012ec91b7948e6f9f2b\">sp_artistbrowse</a> *&nbsp;</td>\n          <td class=\"paramname\"> <em>arb</em>, </td>\n        </tr>\n        <tr>\n          <td class=\"paramkey\"></td>\n          <td></td>\n          <td class=\"paramtype\">int&nbsp;</td>\n          <td class=\"paramname\"> <em>index</em></td><td>&nbsp;</td>\n        </tr>\n        <tr>\n          <td></td>\n          <td>)</td>\n          <td></td><td></td><td></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Creates a link object from an artist portrait</p>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>arb</em>&nbsp;</td><td>Artist browse object </td></tr>\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>index</em>&nbsp;</td><td>The index of the portrait. Should be in the interval [0, <a class=\"el\" href=\"group__artistbrowse.html#ga98dc47d36d2789999bfe62707c5041d7\">sp_artistbrowse_num_portraits()</a> - 1]</td></tr>\n  </table>\n  </dd>\n</dl>\n<dl class=\"return\"><dt><b>Returns:</b></dt><dd>A link object representing an image</dd></dl>\n<dl class=\"note\"><dt><b>Note:</b></dt><dd>You need to release the link when you are done with it. </dd></dl>\n<dl class=\"see\"><dt><b>See also:</b></dt><dd><a class=\"el\" href=\"group__link.html#ga2b06ab16d1f6436cd8d36dbff2b5c022\">sp_link_release()</a> </dd>\n<dd>\n<a class=\"el\" href=\"group__artistbrowse.html#ga98dc47d36d2789999bfe62707c5041d7\">sp_artistbrowse_num_portraits()</a></dd></dl>\n<dl class=\"note\"><dt><b>Note:</b></dt><dd>The difference from <a class=\"el\" href=\"group__link.html#gaafb25ee14bfb27f9cbbab1b039d4d225\">sp_link_create_from_artist_portrait()</a> is that the artist browse object may contain multiple portraits. </dd></dl>\n\n</div>\n</div>\n<a class=\"anchor\" id=\"gaa85fbea312127db44685b7e9dc492042\"></a><!-- doxytag: member=\"api.h::sp_link_create_from_image\" ref=\"gaa85fbea312127db44685b7e9dc492042\" args=\"(sp_image *image)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\"><a class=\"el\" href=\"group__types.html#gaf90a23d6b662c96d52ac19f7f4bc1e39\">sp_link</a>* sp_link_create_from_image </td>\n          <td>(</td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__types.html#ga61155ca7b1ba941e15490e417441917b\">sp_image</a> *&nbsp;</td>\n          <td class=\"paramname\"> <em>image</em></td>\n          <td>&nbsp;)&nbsp;</td>\n          <td></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Create a link object representing the given image</p>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>image</em>&nbsp;</td><td>Image object</td></tr>\n  </table>\n  </dd>\n</dl>\n<dl class=\"return\"><dt><b>Returns:</b></dt><dd>A link representing the image.</dd></dl>\n<dl class=\"note\"><dt><b>Note:</b></dt><dd>You need to release the link when you are done with it. </dd></dl>\n<dl class=\"see\"><dt><b>See also:</b></dt><dd><a class=\"el\" href=\"group__link.html#ga2b06ab16d1f6436cd8d36dbff2b5c022\">sp_link_release()</a> </dd></dl>\n\n</div>\n</div>\n<a class=\"anchor\" id=\"ga805392bfa8e526eebedc1cf5a7bcae0f\"></a><!-- doxytag: member=\"api.h::sp_link_create_from_playlist\" ref=\"ga805392bfa8e526eebedc1cf5a7bcae0f\" args=\"(sp_playlist *playlist)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\"><a class=\"el\" href=\"group__types.html#gaf90a23d6b662c96d52ac19f7f4bc1e39\">sp_link</a>* sp_link_create_from_playlist </td>\n          <td>(</td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__types.html#ga1bcf54cbc117a20ab2c15e59eb3a8174\">sp_playlist</a> *&nbsp;</td>\n          <td class=\"paramname\"> <em>playlist</em></td>\n          <td>&nbsp;)&nbsp;</td>\n          <td></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Create a link object representing the given playlist</p>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>playlist</em>&nbsp;</td><td>Playlist object</td></tr>\n  </table>\n  </dd>\n</dl>\n<dl class=\"return\"><dt><b>Returns:</b></dt><dd>A link representing the playlist</dd></dl>\n<dl class=\"note\"><dt><b>Note:</b></dt><dd>You need to release the link when you are done with it. </dd></dl>\n<dl class=\"see\"><dt><b>See also:</b></dt><dd><a class=\"el\" href=\"group__link.html#ga2b06ab16d1f6436cd8d36dbff2b5c022\">sp_link_release()</a></dd></dl>\n<dl class=\"note\"><dt><b>Note:</b></dt><dd>Due to reasons in the playlist backend design and the Spotify URI scheme you need to wait for the playlist to be loaded before you can successfully construct an URI. If <a class=\"el\" href=\"group__link.html#ga805392bfa8e526eebedc1cf5a7bcae0f\">sp_link_create_from_playlist()</a> returns NULL, try again after teh playlist_state_changed callback has fired. </dd></dl>\n\n</div>\n</div>\n<a class=\"anchor\" id=\"ga95c97ba4de9c4040047276ad618a108e\"></a><!-- doxytag: member=\"api.h::sp_link_create_from_search\" ref=\"ga95c97ba4de9c4040047276ad618a108e\" args=\"(sp_search *search)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\"><a class=\"el\" href=\"group__types.html#gaf90a23d6b662c96d52ac19f7f4bc1e39\">sp_link</a>* sp_link_create_from_search </td>\n          <td>(</td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__types.html#gac95893a6b23d4b19f6f149eed6ead1fd\">sp_search</a> *&nbsp;</td>\n          <td class=\"paramname\"> <em>search</em></td>\n          <td>&nbsp;)&nbsp;</td>\n          <td></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Generate a link object representing the current search</p>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>search</em>&nbsp;</td><td>Search object</td></tr>\n  </table>\n  </dd>\n</dl>\n<dl class=\"return\"><dt><b>Returns:</b></dt><dd>A link representing the search</dd></dl>\n<dl class=\"note\"><dt><b>Note:</b></dt><dd>You need to release the link when you are done with it. </dd></dl>\n<dl class=\"see\"><dt><b>See also:</b></dt><dd><a class=\"el\" href=\"group__link.html#ga2b06ab16d1f6436cd8d36dbff2b5c022\">sp_link_release()</a> </dd></dl>\n\n</div>\n</div>\n<a class=\"anchor\" id=\"gaea9c39f35f7986fc9fed4584fa211127\"></a><!-- doxytag: member=\"api.h::sp_link_create_from_string\" ref=\"gaea9c39f35f7986fc9fed4584fa211127\" args=\"(const char *link)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\"><a class=\"el\" href=\"group__types.html#gaf90a23d6b662c96d52ac19f7f4bc1e39\">sp_link</a>* sp_link_create_from_string </td>\n          <td>(</td>\n          <td class=\"paramtype\">const char *&nbsp;</td>\n          <td class=\"paramname\"> <em>link</em></td>\n          <td>&nbsp;)&nbsp;</td>\n          <td></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Create a Spotify link given a string</p>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>link</em>&nbsp;</td><td>A string representation of a Spotify link</td></tr>\n  </table>\n  </dd>\n</dl>\n<dl class=\"return\"><dt><b>Returns:</b></dt><dd>A link representation of the given string representation. If the link could not be parsed, this function returns NULL.</dd></dl>\n<dl class=\"note\"><dt><b>Note:</b></dt><dd>You need to release the link when you are done with it. </dd></dl>\n<dl class=\"see\"><dt><b>See also:</b></dt><dd><a class=\"el\" href=\"group__link.html#ga6140f924c696d53469bb8930cd53e1e6\">sp_link_type()</a> </dd>\n<dd>\n<a class=\"el\" href=\"group__link.html#ga2b06ab16d1f6436cd8d36dbff2b5c022\">sp_link_release()</a> </dd></dl>\n<dl><dt><b>Examples: </b></dt><dd><a class=\"el\" href=\"browse_8c-example.html#a45\">browse.c</a>.</dd>\n</dl>\n</div>\n</div>\n<a class=\"anchor\" id=\"ga82c29419ce70e2b504670e3d45167d5d\"></a><!-- doxytag: member=\"api.h::sp_link_create_from_track\" ref=\"ga82c29419ce70e2b504670e3d45167d5d\" args=\"(sp_track *track, int offset)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\"><a class=\"el\" href=\"group__types.html#gaf90a23d6b662c96d52ac19f7f4bc1e39\">sp_link</a>* sp_link_create_from_track </td>\n          <td>(</td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__types.html#ga47bbd2262f0c8b5d7147af7d62198e48\">sp_track</a> *&nbsp;</td>\n          <td class=\"paramname\"> <em>track</em>, </td>\n        </tr>\n        <tr>\n          <td class=\"paramkey\"></td>\n          <td></td>\n          <td class=\"paramtype\">int&nbsp;</td>\n          <td class=\"paramname\"> <em>offset</em></td><td>&nbsp;</td>\n        </tr>\n        <tr>\n          <td></td>\n          <td>)</td>\n          <td></td><td></td><td></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Generates a link object from a track</p>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>track</em>&nbsp;</td><td>A track object </td></tr>\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>offset</em>&nbsp;</td><td>Offset in track in ms.</td></tr>\n  </table>\n  </dd>\n</dl>\n<dl class=\"return\"><dt><b>Returns:</b></dt><dd>A link representing the track</dd></dl>\n<dl class=\"note\"><dt><b>Note:</b></dt><dd>You need to release the link when you are done with it. </dd></dl>\n<dl class=\"see\"><dt><b>See also:</b></dt><dd><a class=\"el\" href=\"group__link.html#ga2b06ab16d1f6436cd8d36dbff2b5c022\">sp_link_release()</a> </dd></dl>\n<dl><dt><b>Examples: </b></dt><dd><a class=\"el\" href=\"browse_8c-example.html#a10\">browse.c</a>.</dd>\n</dl>\n</div>\n</div>\n<a class=\"anchor\" id=\"gaaa78b1750179c17f8152408cea43efef\"></a><!-- doxytag: member=\"api.h::sp_link_create_from_user\" ref=\"gaaa78b1750179c17f8152408cea43efef\" args=\"(sp_user *user)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\"><a class=\"el\" href=\"group__types.html#gaf90a23d6b662c96d52ac19f7f4bc1e39\">sp_link</a>* sp_link_create_from_user </td>\n          <td>(</td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__types.html#gaed2dbaa1eebd6752f76613daad9158bc\">sp_user</a> *&nbsp;</td>\n          <td class=\"paramname\"> <em>user</em></td>\n          <td>&nbsp;)&nbsp;</td>\n          <td></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Create a link object representing the given playlist</p>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>user</em>&nbsp;</td><td>User object</td></tr>\n  </table>\n  </dd>\n</dl>\n<dl class=\"return\"><dt><b>Returns:</b></dt><dd>A link representing the profile.</dd></dl>\n<dl class=\"note\"><dt><b>Note:</b></dt><dd>You need to release the link when you are done with it. </dd></dl>\n<dl class=\"see\"><dt><b>See also:</b></dt><dd><a class=\"el\" href=\"group__link.html#ga2b06ab16d1f6436cd8d36dbff2b5c022\">sp_link_release()</a> </dd></dl>\n\n</div>\n</div>\n<a class=\"anchor\" id=\"ga2b06ab16d1f6436cd8d36dbff2b5c022\"></a><!-- doxytag: member=\"api.h::sp_link_release\" ref=\"ga2b06ab16d1f6436cd8d36dbff2b5c022\" args=\"(sp_link *link)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\"><a class=\"el\" href=\"group__error.html#gafd27986ce4cd9eeaeca8adda83c9eb6b\">sp_error</a> sp_link_release </td>\n          <td>(</td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__types.html#gaf90a23d6b662c96d52ac19f7f4bc1e39\">sp_link</a> *&nbsp;</td>\n          <td class=\"paramname\"> <em>link</em></td>\n          <td>&nbsp;)&nbsp;</td>\n          <td></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Decrease the reference count of a link</p>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>link</em>&nbsp;</td><td>The link object </td></tr>\n  </table>\n  </dd>\n</dl>\n<dl class=\"return\"><dt><b>Returns:</b></dt><dd>One of the following errors, from <a class=\"el\" href=\"group__error.html#ga83154178d3a32668658734d2facfa22b\">sp_error</a> SP_ERROR_OK </dd></dl>\n<dl><dt><b>Examples: </b></dt><dd><a class=\"el\" href=\"browse_8c-example.html#a12\">browse.c</a>, and <a class=\"el\" href=\"toplist_8c-example.html#a6\">toplist.c</a>.</dd>\n</dl>\n</div>\n</div>\n<a class=\"anchor\" id=\"ga6140f924c696d53469bb8930cd53e1e6\"></a><!-- doxytag: member=\"api.h::sp_link_type\" ref=\"ga6140f924c696d53469bb8930cd53e1e6\" args=\"(sp_link *link)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\"><a class=\"el\" href=\"group__link.html#gabe9611f04086cdbed6e4e6e1fd913b98\">sp_linktype</a> sp_link_type </td>\n          <td>(</td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__types.html#gaf90a23d6b662c96d52ac19f7f4bc1e39\">sp_link</a> *&nbsp;</td>\n          <td class=\"paramname\"> <em>link</em></td>\n          <td>&nbsp;)&nbsp;</td>\n          <td></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>The link type of the specified link</p>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>link</em>&nbsp;</td><td>The Spotify link whose type you are interested in</td></tr>\n  </table>\n  </dd>\n</dl>\n<dl class=\"return\"><dt><b>Returns:</b></dt><dd>The link type of the specified link - see the sp_linktype enum for possible values </dd></dl>\n<dl><dt><b>Examples: </b></dt><dd><a class=\"el\" href=\"browse_8c-example.html#a46\">browse.c</a>.</dd>\n</dl>\n</div>\n</div>\n</div>\n<hr size=\"1\"><address style=\"text-align: right;\"><small>\nGenerated on Wed Jun 13 2012 14:22:40.<br>\nCopyright &copy; 2006&ndash;2012 Spotify Ltd</small></address>\n</body>\n</html>\n"
  },
  {
    "path": "libspotify/docs/html/group__playlist.html",
    "content": "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\n<html xmlns=\"http://www.w3.org/1999/xhtml\">\n<head>\n<meta http-equiv=\"Content-Type\" content=\"text/xhtml;charset=UTF-8\"/>\n<title>libspotify: Playlist subsystem</title>\n<link href=\"tabs.css\" rel=\"stylesheet\" type=\"text/css\"/>\n<link href=\"doxygen.css\" rel=\"stylesheet\" type=\"text/css\"/>\n</head>\n<body>\n<!-- Generated by Doxygen 1.7.1 -->\n<div class=\"navigation\" id=\"top\">\n  <div class=\"tabs\">\n    <ul class=\"tablist\">\n      <li><a href=\"index.html\"><span>Main&nbsp;Page</span></a></li>\n      <li><a href=\"modules.html\"><span>Modules</span></a></li>\n      <li><a href=\"annotated.html\"><span>Data&nbsp;Structures</span></a></li>\n      <li><a href=\"files.html\"><span>Files</span></a></li>\n      <li><a href=\"examples.html\"><span>Examples</span></a></li>\n    </ul>\n  </div>\n</div>\n<div class=\"header\">\n  <div class=\"summary\">\n<a href=\"#nested-classes\">Data Structures</a> &#124;\n<a href=\"#typedef-members\">Typedefs</a> &#124;\n<a href=\"#func-members\">Functions</a>  </div>\n  <div class=\"headertitle\">\n<h1>Playlist subsystem</h1>  </div>\n</div>\n<div class=\"contents\">\n<table class=\"memberdecls\">\n<tr><td colspan=\"2\"><h2><a name=\"nested-classes\"></a>\nData Structures</h2></td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">struct &nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"structsp__playlist__callbacks.html\">sp_playlist_callbacks</a></td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">struct &nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"structsp__playlistcontainer__callbacks.html\">sp_playlistcontainer_callbacks</a></td></tr>\n<tr><td colspan=\"2\"><h2><a name=\"typedef-members\"></a>\nTypedefs</h2></td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">typedef struct <br class=\"typebreak\"/>\n<a class=\"el\" href=\"structsp__playlist__callbacks.html\">sp_playlist_callbacks</a>&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__playlist.html#ga8249fe3d53c6dce0f154d0bfd3e80c6a\">sp_playlist_callbacks</a></td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">typedef struct <br class=\"typebreak\"/>\n<a class=\"el\" href=\"structsp__playlistcontainer__callbacks.html\">sp_playlistcontainer_callbacks</a>&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__playlist.html#ga8786e3840bb3774fc929183e3a9df281\">sp_playlistcontainer_callbacks</a></td></tr>\n<tr><td colspan=\"2\"><h2><a name=\"func-members\"></a>\nFunctions</h2></td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">bool&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__playlist.html#gaee8ea6c07dfdca3397e27b278fa4870a\">sp_playlist_is_loaded</a> (<a class=\"el\" href=\"group__types.html#ga1bcf54cbc117a20ab2c15e59eb3a8174\">sp_playlist</a> *playlist)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__error.html#gafd27986ce4cd9eeaeca8adda83c9eb6b\">sp_error</a>&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__playlist.html#gab15fca12d387c69b4998a4d2b48e5b32\">sp_playlist_add_callbacks</a> (<a class=\"el\" href=\"group__types.html#ga1bcf54cbc117a20ab2c15e59eb3a8174\">sp_playlist</a> *playlist, <a class=\"el\" href=\"structsp__playlist__callbacks.html\">sp_playlist_callbacks</a> *callbacks, void *userdata)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__error.html#gafd27986ce4cd9eeaeca8adda83c9eb6b\">sp_error</a>&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__playlist.html#ga7fcbf909a0fa8bf25f0b1d1e7dd0e160\">sp_playlist_remove_callbacks</a> (<a class=\"el\" href=\"group__types.html#ga1bcf54cbc117a20ab2c15e59eb3a8174\">sp_playlist</a> *playlist, <a class=\"el\" href=\"structsp__playlist__callbacks.html\">sp_playlist_callbacks</a> *callbacks, void *userdata)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">int&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__playlist.html#ga684a3acc60f99b3b26488ed813ee5d23\">sp_playlist_num_tracks</a> (<a class=\"el\" href=\"group__types.html#ga1bcf54cbc117a20ab2c15e59eb3a8174\">sp_playlist</a> *playlist)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__types.html#ga47bbd2262f0c8b5d7147af7d62198e48\">sp_track</a> *&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__playlist.html#ga7a03854fe6072476306780d23c6cac16\">sp_playlist_track</a> (<a class=\"el\" href=\"group__types.html#ga1bcf54cbc117a20ab2c15e59eb3a8174\">sp_playlist</a> *playlist, int index)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">int&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__playlist.html#gab8e77f8d63e787f8aa1a066d74daa74c\">sp_playlist_track_create_time</a> (<a class=\"el\" href=\"group__types.html#ga1bcf54cbc117a20ab2c15e59eb3a8174\">sp_playlist</a> *playlist, int index)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__types.html#gaed2dbaa1eebd6752f76613daad9158bc\">sp_user</a> *&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__playlist.html#ga80fcd9e7b40c791433c07d66e2ad432a\">sp_playlist_track_creator</a> (<a class=\"el\" href=\"group__types.html#ga1bcf54cbc117a20ab2c15e59eb3a8174\">sp_playlist</a> *playlist, int index)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">bool&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__playlist.html#gab9e00ee5bc6b5dc0b3d58cbdb32c0c7b\">sp_playlist_track_seen</a> (<a class=\"el\" href=\"group__types.html#ga1bcf54cbc117a20ab2c15e59eb3a8174\">sp_playlist</a> *playlist, int index)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__error.html#gafd27986ce4cd9eeaeca8adda83c9eb6b\">sp_error</a>&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__playlist.html#ga69f5cc1bdd7dbdcdb476a7b1d2b7834d\">sp_playlist_track_set_seen</a> (<a class=\"el\" href=\"group__types.html#ga1bcf54cbc117a20ab2c15e59eb3a8174\">sp_playlist</a> *playlist, int index, bool seen)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">const char *&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__playlist.html#ga6887b9dabb30a060b10bdb75f8b3f971\">sp_playlist_track_message</a> (<a class=\"el\" href=\"group__types.html#ga1bcf54cbc117a20ab2c15e59eb3a8174\">sp_playlist</a> *playlist, int index)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">const char *&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__playlist.html#ga61b7e33cc1aedb4e31a2af75ae0ac8cc\">sp_playlist_name</a> (<a class=\"el\" href=\"group__types.html#ga1bcf54cbc117a20ab2c15e59eb3a8174\">sp_playlist</a> *playlist)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__error.html#gafd27986ce4cd9eeaeca8adda83c9eb6b\">sp_error</a>&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__playlist.html#gad6c3880c514353e204fdd90830b516ec\">sp_playlist_rename</a> (<a class=\"el\" href=\"group__types.html#ga1bcf54cbc117a20ab2c15e59eb3a8174\">sp_playlist</a> *playlist, const char *new_name)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__types.html#gaed2dbaa1eebd6752f76613daad9158bc\">sp_user</a> *&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__playlist.html#gac3e4295d3353eb9998402aedfdbd55de\">sp_playlist_owner</a> (<a class=\"el\" href=\"group__types.html#ga1bcf54cbc117a20ab2c15e59eb3a8174\">sp_playlist</a> *playlist)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">bool&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__playlist.html#ga8ad160f654f02f13690568070dd57353\">sp_playlist_is_collaborative</a> (<a class=\"el\" href=\"group__types.html#ga1bcf54cbc117a20ab2c15e59eb3a8174\">sp_playlist</a> *playlist)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__error.html#gafd27986ce4cd9eeaeca8adda83c9eb6b\">sp_error</a>&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__playlist.html#gad15410bcc2ebd986adabda865830bce4\">sp_playlist_set_collaborative</a> (<a class=\"el\" href=\"group__types.html#ga1bcf54cbc117a20ab2c15e59eb3a8174\">sp_playlist</a> *playlist, bool collaborative)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__error.html#gafd27986ce4cd9eeaeca8adda83c9eb6b\">sp_error</a>&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__playlist.html#ga0bde47f340e0cd590a78007c6af69307\">sp_playlist_set_autolink_tracks</a> (<a class=\"el\" href=\"group__types.html#ga1bcf54cbc117a20ab2c15e59eb3a8174\">sp_playlist</a> *playlist, bool link)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">const char *&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__playlist.html#gab1d8e0ee9b436ecbb104bbd6cc0665be\">sp_playlist_get_description</a> (<a class=\"el\" href=\"group__types.html#ga1bcf54cbc117a20ab2c15e59eb3a8174\">sp_playlist</a> *playlist)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">bool&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__playlist.html#ga409cb6b2a88db7242ec939b6644e8c30\">sp_playlist_get_image</a> (<a class=\"el\" href=\"group__types.html#ga1bcf54cbc117a20ab2c15e59eb3a8174\">sp_playlist</a> *playlist, byte image[20])</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">bool&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__playlist.html#gaf0e39b5969259d10625eb398af0f3f43\">sp_playlist_has_pending_changes</a> (<a class=\"el\" href=\"group__types.html#ga1bcf54cbc117a20ab2c15e59eb3a8174\">sp_playlist</a> *playlist)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__error.html#gafd27986ce4cd9eeaeca8adda83c9eb6b\">sp_error</a>&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__playlist.html#ga2344a47133f7f0aed0a67e154ecc4dc4\">sp_playlist_add_tracks</a> (<a class=\"el\" href=\"group__types.html#ga1bcf54cbc117a20ab2c15e59eb3a8174\">sp_playlist</a> *playlist, <a class=\"el\" href=\"group__types.html#ga47bbd2262f0c8b5d7147af7d62198e48\">sp_track</a> *const *tracks, int num_tracks, int position, <a class=\"el\" href=\"group__types.html#ga70dd19c6f824cf6a159575aa4c128b53\">sp_session</a> *session)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__error.html#gafd27986ce4cd9eeaeca8adda83c9eb6b\">sp_error</a>&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__playlist.html#gabd62cd7ff9484b4c31ff7f159ec41b6a\">sp_playlist_remove_tracks</a> (<a class=\"el\" href=\"group__types.html#ga1bcf54cbc117a20ab2c15e59eb3a8174\">sp_playlist</a> *playlist, const int *tracks, int num_tracks)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__error.html#gafd27986ce4cd9eeaeca8adda83c9eb6b\">sp_error</a>&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__playlist.html#ga90ffd8c9fc6abc7375e89f4cb49adb11\">sp_playlist_reorder_tracks</a> (<a class=\"el\" href=\"group__types.html#ga1bcf54cbc117a20ab2c15e59eb3a8174\">sp_playlist</a> *playlist, const int *tracks, int num_tracks, int new_position)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">unsigned int&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__playlist.html#ga967ad87f0db702513ecda82546f667c5\">sp_playlist_num_subscribers</a> (<a class=\"el\" href=\"group__types.html#ga1bcf54cbc117a20ab2c15e59eb3a8174\">sp_playlist</a> *playlist)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"structsp__subscribers.html\">sp_subscribers</a> *&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__playlist.html#gad49f491babc475f8d4aeea1b4452ff8b\">sp_playlist_subscribers</a> (<a class=\"el\" href=\"group__types.html#ga1bcf54cbc117a20ab2c15e59eb3a8174\">sp_playlist</a> *playlist)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__error.html#gafd27986ce4cd9eeaeca8adda83c9eb6b\">sp_error</a>&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__playlist.html#gae7754b74b1c3c8f5222ca43b6608ce6a\">sp_playlist_subscribers_free</a> (<a class=\"el\" href=\"structsp__subscribers.html\">sp_subscribers</a> *subscribers)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__error.html#gafd27986ce4cd9eeaeca8adda83c9eb6b\">sp_error</a>&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__playlist.html#ga9ebbf147230b3ca98b68e556cf24e6bd\">sp_playlist_update_subscribers</a> (<a class=\"el\" href=\"group__types.html#ga70dd19c6f824cf6a159575aa4c128b53\">sp_session</a> *session, <a class=\"el\" href=\"group__types.html#ga1bcf54cbc117a20ab2c15e59eb3a8174\">sp_playlist</a> *playlist)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">bool&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__playlist.html#ga28456d1242693c6d890516dc782ab3ec\">sp_playlist_is_in_ram</a> (<a class=\"el\" href=\"group__types.html#ga70dd19c6f824cf6a159575aa4c128b53\">sp_session</a> *session, <a class=\"el\" href=\"group__types.html#ga1bcf54cbc117a20ab2c15e59eb3a8174\">sp_playlist</a> *playlist)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__error.html#gafd27986ce4cd9eeaeca8adda83c9eb6b\">sp_error</a>&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__playlist.html#gaf6ca8a349bdd982f6c8dda52ed691017\">sp_playlist_set_in_ram</a> (<a class=\"el\" href=\"group__types.html#ga70dd19c6f824cf6a159575aa4c128b53\">sp_session</a> *session, <a class=\"el\" href=\"group__types.html#ga1bcf54cbc117a20ab2c15e59eb3a8174\">sp_playlist</a> *playlist, bool in_ram)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__types.html#ga1bcf54cbc117a20ab2c15e59eb3a8174\">sp_playlist</a> *&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__playlist.html#ga342a6a0cfe10531ef7cb3c6629c1e8e7\">sp_playlist_create</a> (<a class=\"el\" href=\"group__types.html#ga70dd19c6f824cf6a159575aa4c128b53\">sp_session</a> *session, <a class=\"el\" href=\"group__types.html#gaf90a23d6b662c96d52ac19f7f4bc1e39\">sp_link</a> *link)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__error.html#gafd27986ce4cd9eeaeca8adda83c9eb6b\">sp_error</a>&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__playlist.html#ga784f648f9cc431ef3b51f3491c2f169f\">sp_playlist_set_offline_mode</a> (<a class=\"el\" href=\"group__types.html#ga70dd19c6f824cf6a159575aa4c128b53\">sp_session</a> *session, <a class=\"el\" href=\"group__types.html#ga1bcf54cbc117a20ab2c15e59eb3a8174\">sp_playlist</a> *playlist, bool offline)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__session.html#ga811fa52ed0fdb5cda732682e27e40417\">sp_playlist_offline_status</a>&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__playlist.html#ga7170157af21445c37a21a2241f91ff06\">sp_playlist_get_offline_status</a> (<a class=\"el\" href=\"group__types.html#ga70dd19c6f824cf6a159575aa4c128b53\">sp_session</a> *session, <a class=\"el\" href=\"group__types.html#ga1bcf54cbc117a20ab2c15e59eb3a8174\">sp_playlist</a> *playlist)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">int&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__playlist.html#ga83ca1a25f50834f8e6f8ee1e883a8c6e\">sp_playlist_get_offline_download_completed</a> (<a class=\"el\" href=\"group__types.html#ga70dd19c6f824cf6a159575aa4c128b53\">sp_session</a> *session, <a class=\"el\" href=\"group__types.html#ga1bcf54cbc117a20ab2c15e59eb3a8174\">sp_playlist</a> *playlist)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__error.html#gafd27986ce4cd9eeaeca8adda83c9eb6b\">sp_error</a>&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__playlist.html#gacb10979add5a954e5c1600ef9c5b17a8\">sp_playlist_add_ref</a> (<a class=\"el\" href=\"group__types.html#ga1bcf54cbc117a20ab2c15e59eb3a8174\">sp_playlist</a> *playlist)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__error.html#gafd27986ce4cd9eeaeca8adda83c9eb6b\">sp_error</a>&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__playlist.html#gacb9250eb530869b039541a8b62dfab6c\">sp_playlist_release</a> (<a class=\"el\" href=\"group__types.html#ga1bcf54cbc117a20ab2c15e59eb3a8174\">sp_playlist</a> *playlist)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__error.html#gafd27986ce4cd9eeaeca8adda83c9eb6b\">sp_error</a>&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__playlist.html#ga1976cb49c391cdd2dbe7c40d1bc71570\">sp_playlistcontainer_add_callbacks</a> (<a class=\"el\" href=\"group__types.html#ga45a2febbe167483e48dab8d606d462d7\">sp_playlistcontainer</a> *pc, <a class=\"el\" href=\"structsp__playlistcontainer__callbacks.html\">sp_playlistcontainer_callbacks</a> *callbacks, void *userdata)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__error.html#gafd27986ce4cd9eeaeca8adda83c9eb6b\">sp_error</a>&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__playlist.html#gafb5242b8f0f9964cec29d32f4d6c1164\">sp_playlistcontainer_remove_callbacks</a> (<a class=\"el\" href=\"group__types.html#ga45a2febbe167483e48dab8d606d462d7\">sp_playlistcontainer</a> *pc, <a class=\"el\" href=\"structsp__playlistcontainer__callbacks.html\">sp_playlistcontainer_callbacks</a> *callbacks, void *userdata)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">int&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__playlist.html#ga7a1cbf558b2b364b8249d4ce432df700\">sp_playlistcontainer_num_playlists</a> (<a class=\"el\" href=\"group__types.html#ga45a2febbe167483e48dab8d606d462d7\">sp_playlistcontainer</a> *pc)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">bool&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__playlist.html#gae23cb67b4b26bca663034997c4418fa8\">sp_playlistcontainer_is_loaded</a> (<a class=\"el\" href=\"group__types.html#ga45a2febbe167483e48dab8d606d462d7\">sp_playlistcontainer</a> *pc)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__types.html#ga1bcf54cbc117a20ab2c15e59eb3a8174\">sp_playlist</a> *&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__playlist.html#ga5ddd8c8064c281a14c6fd7877f522dc6\">sp_playlistcontainer_playlist</a> (<a class=\"el\" href=\"group__types.html#ga45a2febbe167483e48dab8d606d462d7\">sp_playlistcontainer</a> *pc, int index)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__session.html#gafdd7117213605e6f2671c4f289b44609\">sp_playlist_type</a>&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__playlist.html#ga79286860a3eeada495e97c5ad1fd7ebf\">sp_playlistcontainer_playlist_type</a> (<a class=\"el\" href=\"group__types.html#ga45a2febbe167483e48dab8d606d462d7\">sp_playlistcontainer</a> *pc, int index)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__error.html#gafd27986ce4cd9eeaeca8adda83c9eb6b\">sp_error</a>&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__playlist.html#ga852e5f5bcd4520be2e3d6d5d94def44a\">sp_playlistcontainer_playlist_folder_name</a> (<a class=\"el\" href=\"group__types.html#ga45a2febbe167483e48dab8d606d462d7\">sp_playlistcontainer</a> *pc, int index, char *buffer, int buffer_size)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">sp_uint64&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__playlist.html#ga6939f9db71199612fc5a19d395e3a7f8\">sp_playlistcontainer_playlist_folder_id</a> (<a class=\"el\" href=\"group__types.html#ga45a2febbe167483e48dab8d606d462d7\">sp_playlistcontainer</a> *pc, int index)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__types.html#ga1bcf54cbc117a20ab2c15e59eb3a8174\">sp_playlist</a> *&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__playlist.html#ga840b82b1074a7ca1c9eacd351bed24c2\">sp_playlistcontainer_add_new_playlist</a> (<a class=\"el\" href=\"group__types.html#ga45a2febbe167483e48dab8d606d462d7\">sp_playlistcontainer</a> *pc, const char *name)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__types.html#ga1bcf54cbc117a20ab2c15e59eb3a8174\">sp_playlist</a> *&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__playlist.html#ga87699479087915b741ceef4eebe69ad8\">sp_playlistcontainer_add_playlist</a> (<a class=\"el\" href=\"group__types.html#ga45a2febbe167483e48dab8d606d462d7\">sp_playlistcontainer</a> *pc, <a class=\"el\" href=\"group__types.html#gaf90a23d6b662c96d52ac19f7f4bc1e39\">sp_link</a> *link)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__error.html#gafd27986ce4cd9eeaeca8adda83c9eb6b\">sp_error</a>&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__playlist.html#ga1ae1d51c4305940ae5c5c98c12be0afc\">sp_playlistcontainer_remove_playlist</a> (<a class=\"el\" href=\"group__types.html#ga45a2febbe167483e48dab8d606d462d7\">sp_playlistcontainer</a> *pc, int index)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__error.html#gafd27986ce4cd9eeaeca8adda83c9eb6b\">sp_error</a>&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__playlist.html#gad9be708159957d4c1e5ef905550808c5\">sp_playlistcontainer_move_playlist</a> (<a class=\"el\" href=\"group__types.html#ga45a2febbe167483e48dab8d606d462d7\">sp_playlistcontainer</a> *pc, int index, int new_position, bool dry_run)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__error.html#gafd27986ce4cd9eeaeca8adda83c9eb6b\">sp_error</a>&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__playlist.html#ga0862502eea52fc5f2465ebad6fd98796\">sp_playlistcontainer_add_folder</a> (<a class=\"el\" href=\"group__types.html#ga45a2febbe167483e48dab8d606d462d7\">sp_playlistcontainer</a> *pc, int index, const char *name)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__types.html#gaed2dbaa1eebd6752f76613daad9158bc\">sp_user</a> *&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__playlist.html#gad4fc67d1386dd637f778f4e735a36894\">sp_playlistcontainer_owner</a> (<a class=\"el\" href=\"group__types.html#ga45a2febbe167483e48dab8d606d462d7\">sp_playlistcontainer</a> *pc)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__error.html#gafd27986ce4cd9eeaeca8adda83c9eb6b\">sp_error</a>&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__playlist.html#ga2138c537a6ebcd35a01eea54d0dd1e8f\">sp_playlistcontainer_add_ref</a> (<a class=\"el\" href=\"group__types.html#ga45a2febbe167483e48dab8d606d462d7\">sp_playlistcontainer</a> *pc)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__error.html#gafd27986ce4cd9eeaeca8adda83c9eb6b\">sp_error</a>&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__playlist.html#ga0311c7c3c4f26028e5edd4aacb36dbf8\">sp_playlistcontainer_release</a> (<a class=\"el\" href=\"group__types.html#ga45a2febbe167483e48dab8d606d462d7\">sp_playlistcontainer</a> *pc)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">int&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__playlist.html#gad9e11b45843ee4a147b43038a2e55f13\">sp_playlistcontainer_get_unseen_tracks</a> (<a class=\"el\" href=\"group__types.html#ga45a2febbe167483e48dab8d606d462d7\">sp_playlistcontainer</a> *pc, <a class=\"el\" href=\"group__types.html#ga1bcf54cbc117a20ab2c15e59eb3a8174\">sp_playlist</a> *playlist, <a class=\"el\" href=\"group__types.html#ga47bbd2262f0c8b5d7147af7d62198e48\">sp_track</a> **tracks, int num_tracks)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">int&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__playlist.html#gadaad604c35e543363e1dd5b23c462db0\">sp_playlistcontainer_clear_unseen_tracks</a> (<a class=\"el\" href=\"group__types.html#ga45a2febbe167483e48dab8d606d462d7\">sp_playlistcontainer</a> *pc, <a class=\"el\" href=\"group__types.html#ga1bcf54cbc117a20ab2c15e59eb3a8174\">sp_playlist</a> *playlist)</td></tr>\n</table>\n<hr/><a name=\"_details\"></a><h2>Detailed Description</h2>\n<p>The playlist subsystem handles playlists and playlist containers (list of playlists).</p>\n<p>The playlist container functions are always valid, but your playlists are not guaranteed to be loaded until the <a class=\"el\" href=\"structsp__session__callbacks.html#a52d509962541f7d8fdd71284f40d8415\">sp_session_callbacks::logged_in</a> callback has been issued. </p>\n<hr/><h2>Typedef Documentation</h2>\n<a class=\"anchor\" id=\"ga8249fe3d53c6dce0f154d0bfd3e80c6a\"></a><!-- doxytag: member=\"api.h::sp_playlist_callbacks\" ref=\"ga8249fe3d53c6dce0f154d0bfd3e80c6a\" args=\"\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\">typedef struct <a class=\"el\" href=\"structsp__playlist__callbacks.html\">sp_playlist_callbacks</a>  <a class=\"el\" href=\"structsp__playlist__callbacks.html\">sp_playlist_callbacks</a></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Playlist callbacks</p>\n<p>Used to get notifications when playlists are updated. If some callbacks should not be of interest, set them to NULL. </p>\n\n</div>\n</div>\n<a class=\"anchor\" id=\"ga8786e3840bb3774fc929183e3a9df281\"></a><!-- doxytag: member=\"api.h::sp_playlistcontainer_callbacks\" ref=\"ga8786e3840bb3774fc929183e3a9df281\" args=\"\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\">typedef struct <a class=\"el\" href=\"structsp__playlistcontainer__callbacks.html\">sp_playlistcontainer_callbacks</a>  <a class=\"el\" href=\"structsp__playlistcontainer__callbacks.html\">sp_playlistcontainer_callbacks</a></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Playlist container callbacks. If some callbacks should not be of interest, set them to NULL.</p>\n<dl class=\"see\"><dt><b>See also:</b></dt><dd><a class=\"el\" href=\"group__playlist.html#ga1976cb49c391cdd2dbe7c40d1bc71570\">sp_playlistcontainer_add_callbacks</a> </dd>\n<dd>\n<a class=\"el\" href=\"group__playlist.html#gafb5242b8f0f9964cec29d32f4d6c1164\">sp_playlistcontainer_remove_callbacks</a> </dd></dl>\n\n</div>\n</div>\n<hr/><h2>Function Documentation</h2>\n<a class=\"anchor\" id=\"gab15fca12d387c69b4998a4d2b48e5b32\"></a><!-- doxytag: member=\"api.h::sp_playlist_add_callbacks\" ref=\"gab15fca12d387c69b4998a4d2b48e5b32\" args=\"(sp_playlist *playlist, sp_playlist_callbacks *callbacks, void *userdata)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\"><a class=\"el\" href=\"group__error.html#gafd27986ce4cd9eeaeca8adda83c9eb6b\">sp_error</a> sp_playlist_add_callbacks </td>\n          <td>(</td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__types.html#ga1bcf54cbc117a20ab2c15e59eb3a8174\">sp_playlist</a> *&nbsp;</td>\n          <td class=\"paramname\"> <em>playlist</em>, </td>\n        </tr>\n        <tr>\n          <td class=\"paramkey\"></td>\n          <td></td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"structsp__playlist__callbacks.html\">sp_playlist_callbacks</a> *&nbsp;</td>\n          <td class=\"paramname\"> <em>callbacks</em>, </td>\n        </tr>\n        <tr>\n          <td class=\"paramkey\"></td>\n          <td></td>\n          <td class=\"paramtype\">void *&nbsp;</td>\n          <td class=\"paramname\"> <em>userdata</em></td><td>&nbsp;</td>\n        </tr>\n        <tr>\n          <td></td>\n          <td>)</td>\n          <td></td><td></td><td></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Register interest in the given playlist</p>\n<p>Here is a snippet from <code>jukebox.c:</code>  <div class=\"fragment\"><pre class=\"fragment\">    <a class=\"code\" href=\"group__playlist.html#gab15fca12d387c69b4998a4d2b48e5b32\">sp_playlist_add_callbacks</a>(pl, &amp;pl_callbacks, NULL);\n</pre></div></p>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>playlist</em>&nbsp;</td><td>Playlist object </td></tr>\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>callbacks</em>&nbsp;</td><td>Callbacks, see <a class=\"el\" href=\"structsp__playlist__callbacks.html\">sp_playlist_callbacks</a> </td></tr>\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>userdata</em>&nbsp;</td><td>Userdata to be passed to callbacks </td></tr>\n  </table>\n  </dd>\n</dl>\n<dl class=\"see\"><dt><b>See also:</b></dt><dd><a class=\"el\" href=\"group__playlist.html#ga7fcbf909a0fa8bf25f0b1d1e7dd0e160\">sp_playlist_remove_callbacks</a> </dd></dl>\n<dl><dt><b>Examples: </b></dt><dd><a class=\"el\" href=\"browse_8c-example.html#a44\">browse.c</a>, and <a class=\"el\" href=\"jukebox_8c-example.html#a10\">jukebox.c</a>.</dd>\n</dl>\n</div>\n</div>\n<a class=\"anchor\" id=\"gacb10979add5a954e5c1600ef9c5b17a8\"></a><!-- doxytag: member=\"api.h::sp_playlist_add_ref\" ref=\"gacb10979add5a954e5c1600ef9c5b17a8\" args=\"(sp_playlist *playlist)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\"><a class=\"el\" href=\"group__error.html#gafd27986ce4cd9eeaeca8adda83c9eb6b\">sp_error</a> sp_playlist_add_ref </td>\n          <td>(</td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__types.html#ga1bcf54cbc117a20ab2c15e59eb3a8174\">sp_playlist</a> *&nbsp;</td>\n          <td class=\"paramname\"> <em>playlist</em></td>\n          <td>&nbsp;)&nbsp;</td>\n          <td></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Increase the reference count of a playlist</p>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>playlist</em>&nbsp;</td><td>The playlist object </td></tr>\n  </table>\n  </dd>\n</dl>\n<dl class=\"return\"><dt><b>Returns:</b></dt><dd>One of the following errors, from <a class=\"el\" href=\"group__error.html#ga83154178d3a32668658734d2facfa22b\">sp_error</a> SP_ERROR_OK </dd></dl>\n\n</div>\n</div>\n<a class=\"anchor\" id=\"ga2344a47133f7f0aed0a67e154ecc4dc4\"></a><!-- doxytag: member=\"api.h::sp_playlist_add_tracks\" ref=\"ga2344a47133f7f0aed0a67e154ecc4dc4\" args=\"(sp_playlist *playlist, sp_track *const *tracks, int num_tracks, int position, sp_session *session)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\"><a class=\"el\" href=\"group__error.html#gafd27986ce4cd9eeaeca8adda83c9eb6b\">sp_error</a> sp_playlist_add_tracks </td>\n          <td>(</td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__types.html#ga1bcf54cbc117a20ab2c15e59eb3a8174\">sp_playlist</a> *&nbsp;</td>\n          <td class=\"paramname\"> <em>playlist</em>, </td>\n        </tr>\n        <tr>\n          <td class=\"paramkey\"></td>\n          <td></td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__types.html#ga47bbd2262f0c8b5d7147af7d62198e48\">sp_track</a> *const *&nbsp;</td>\n          <td class=\"paramname\"> <em>tracks</em>, </td>\n        </tr>\n        <tr>\n          <td class=\"paramkey\"></td>\n          <td></td>\n          <td class=\"paramtype\">int&nbsp;</td>\n          <td class=\"paramname\"> <em>num_tracks</em>, </td>\n        </tr>\n        <tr>\n          <td class=\"paramkey\"></td>\n          <td></td>\n          <td class=\"paramtype\">int&nbsp;</td>\n          <td class=\"paramname\"> <em>position</em>, </td>\n        </tr>\n        <tr>\n          <td class=\"paramkey\"></td>\n          <td></td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__types.html#ga70dd19c6f824cf6a159575aa4c128b53\">sp_session</a> *&nbsp;</td>\n          <td class=\"paramname\"> <em>session</em></td><td>&nbsp;</td>\n        </tr>\n        <tr>\n          <td></td>\n          <td>)</td>\n          <td></td><td></td><td></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Add tracks to a playlist</p>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>playlist</em>&nbsp;</td><td>Playlist object </td></tr>\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>tracks</em>&nbsp;</td><td>Array of pointer to tracks. </td></tr>\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>num_tracks</em>&nbsp;</td><td>Length of <code>tracks</code> array </td></tr>\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>position</em>&nbsp;</td><td>Start position in playlist where to insert the tracks </td></tr>\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>session</em>&nbsp;</td><td>Your session object</td></tr>\n  </table>\n  </dd>\n</dl>\n<dl class=\"return\"><dt><b>Returns:</b></dt><dd>One of the following errors, from <a class=\"el\" href=\"group__error.html#ga83154178d3a32668658734d2facfa22b\">sp_error</a> SP_ERROR_OK SP_ERROR_INVALID_INDATA - position is &gt; current playlist length SP_ERROR_PERMISSION_DENIED </dd></dl>\n\n</div>\n</div>\n<a class=\"anchor\" id=\"ga342a6a0cfe10531ef7cb3c6629c1e8e7\"></a><!-- doxytag: member=\"api.h::sp_playlist_create\" ref=\"ga342a6a0cfe10531ef7cb3c6629c1e8e7\" args=\"(sp_session *session, sp_link *link)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\"><a class=\"el\" href=\"group__types.html#ga1bcf54cbc117a20ab2c15e59eb3a8174\">sp_playlist</a>* sp_playlist_create </td>\n          <td>(</td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__types.html#ga70dd19c6f824cf6a159575aa4c128b53\">sp_session</a> *&nbsp;</td>\n          <td class=\"paramname\"> <em>session</em>, </td>\n        </tr>\n        <tr>\n          <td class=\"paramkey\"></td>\n          <td></td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__types.html#gaf90a23d6b662c96d52ac19f7f4bc1e39\">sp_link</a> *&nbsp;</td>\n          <td class=\"paramname\"> <em>link</em></td><td>&nbsp;</td>\n        </tr>\n        <tr>\n          <td></td>\n          <td>)</td>\n          <td></td><td></td><td></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Load an already existing playlist without adding it to a playlistcontainer.</p>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>session</em>&nbsp;</td><td>Session object </td></tr>\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>link</em>&nbsp;</td><td>Link object referring to a playlist</td></tr>\n  </table>\n  </dd>\n</dl>\n<dl class=\"return\"><dt><b>Returns:</b></dt><dd>A playlist. The reference is owned by the caller and should be released with <a class=\"el\" href=\"group__playlist.html#gacb9250eb530869b039541a8b62dfab6c\">sp_playlist_release()</a> </dd></dl>\n<dl><dt><b>Examples: </b></dt><dd><a class=\"el\" href=\"browse_8c-example.html#a59\">browse.c</a>.</dd>\n</dl>\n</div>\n</div>\n<a class=\"anchor\" id=\"gab1d8e0ee9b436ecbb104bbd6cc0665be\"></a><!-- doxytag: member=\"api.h::sp_playlist_get_description\" ref=\"gab1d8e0ee9b436ecbb104bbd6cc0665be\" args=\"(sp_playlist *playlist)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\">const char* sp_playlist_get_description </td>\n          <td>(</td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__types.html#ga1bcf54cbc117a20ab2c15e59eb3a8174\">sp_playlist</a> *&nbsp;</td>\n          <td class=\"paramname\"> <em>playlist</em></td>\n          <td>&nbsp;)&nbsp;</td>\n          <td></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Get description for a playlist</p>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>playlist</em>&nbsp;</td><td>Playlist object</td></tr>\n  </table>\n  </dd>\n</dl>\n<dl class=\"return\"><dt><b>Returns:</b></dt><dd>Playlist description or NULL if unset </dd></dl>\n\n</div>\n</div>\n<a class=\"anchor\" id=\"ga409cb6b2a88db7242ec939b6644e8c30\"></a><!-- doxytag: member=\"api.h::sp_playlist_get_image\" ref=\"ga409cb6b2a88db7242ec939b6644e8c30\" args=\"(sp_playlist *playlist, byte image[20])\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\">bool sp_playlist_get_image </td>\n          <td>(</td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__types.html#ga1bcf54cbc117a20ab2c15e59eb3a8174\">sp_playlist</a> *&nbsp;</td>\n          <td class=\"paramname\"> <em>playlist</em>, </td>\n        </tr>\n        <tr>\n          <td class=\"paramkey\"></td>\n          <td></td>\n          <td class=\"paramtype\">byte&nbsp;</td>\n          <td class=\"paramname\"> <em>image</em>[20]</td><td>&nbsp;</td>\n        </tr>\n        <tr>\n          <td></td>\n          <td>)</td>\n          <td></td><td></td><td></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Get description for a playlist</p>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>playlist</em>&nbsp;</td><td>Playlist object </td></tr>\n    <tr><td valign=\"top\"><tt>[out]</tt>&nbsp;</td><td valign=\"top\"><em>image</em>&nbsp;</td><td>20 byte image id</td></tr>\n  </table>\n  </dd>\n</dl>\n<dl class=\"return\"><dt><b>Returns:</b></dt><dd>TRUE if playlist has an image, FALSE if not </dd></dl>\n\n</div>\n</div>\n<a class=\"anchor\" id=\"ga83ca1a25f50834f8e6f8ee1e883a8c6e\"></a><!-- doxytag: member=\"api.h::sp_playlist_get_offline_download_completed\" ref=\"ga83ca1a25f50834f8e6f8ee1e883a8c6e\" args=\"(sp_session *session, sp_playlist *playlist)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\">int sp_playlist_get_offline_download_completed </td>\n          <td>(</td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__types.html#ga70dd19c6f824cf6a159575aa4c128b53\">sp_session</a> *&nbsp;</td>\n          <td class=\"paramname\"> <em>session</em>, </td>\n        </tr>\n        <tr>\n          <td class=\"paramkey\"></td>\n          <td></td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__types.html#ga1bcf54cbc117a20ab2c15e59eb3a8174\">sp_playlist</a> *&nbsp;</td>\n          <td class=\"paramname\"> <em>playlist</em></td><td>&nbsp;</td>\n        </tr>\n        <tr>\n          <td></td>\n          <td>)</td>\n          <td></td><td></td><td></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Get download progress for an offline playlist</p>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>session</em>&nbsp;</td><td>Session object </td></tr>\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>playlist</em>&nbsp;</td><td>Playlist object</td></tr>\n  </table>\n  </dd>\n</dl>\n<dl class=\"return\"><dt><b>Returns:</b></dt><dd>Value from 0 - 100 that indicates amount of playlist that is downloaded or 0 if the playlist is not in the SP_PLAYLIST_OFFLINE_STATUS_DOWNLOADING mode.</dd></dl>\n<dl class=\"see\"><dt><b>See also:</b></dt><dd><a class=\"el\" href=\"group__session.html#ga811fa52ed0fdb5cda732682e27e40417\">sp_playlist_offline_status()</a> </dd></dl>\n\n</div>\n</div>\n<a class=\"anchor\" id=\"ga7170157af21445c37a21a2241f91ff06\"></a><!-- doxytag: member=\"api.h::sp_playlist_get_offline_status\" ref=\"ga7170157af21445c37a21a2241f91ff06\" args=\"(sp_session *session, sp_playlist *playlist)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\"><a class=\"el\" href=\"group__session.html#ga811fa52ed0fdb5cda732682e27e40417\">sp_playlist_offline_status</a> sp_playlist_get_offline_status </td>\n          <td>(</td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__types.html#ga70dd19c6f824cf6a159575aa4c128b53\">sp_session</a> *&nbsp;</td>\n          <td class=\"paramname\"> <em>session</em>, </td>\n        </tr>\n        <tr>\n          <td class=\"paramkey\"></td>\n          <td></td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__types.html#ga1bcf54cbc117a20ab2c15e59eb3a8174\">sp_playlist</a> *&nbsp;</td>\n          <td class=\"paramname\"> <em>playlist</em></td><td>&nbsp;</td>\n        </tr>\n        <tr>\n          <td></td>\n          <td>)</td>\n          <td></td><td></td><td></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Get offline status for a playlist</p>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>session</em>&nbsp;</td><td>Session object </td></tr>\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>playlist</em>&nbsp;</td><td>Playlist object</td></tr>\n  </table>\n  </dd>\n</dl>\n<dl class=\"return\"><dt><b>Returns:</b></dt><dd>sp_playlist_offline_status</dd></dl>\n<dl class=\"see\"><dt><b>See also:</b></dt><dd>When in <a class=\"el\" href=\"group__session.html#gga811fa52ed0fdb5cda732682e27e40417abc999c70761d392b26753708e9a2cfa1\" title=\"This playlist is currently downloading. Only one playlist can be in this state any given time...\">SP_PLAYLIST_OFFLINE_STATUS_DOWNLOADING</a> mode the <a class=\"el\" href=\"group__playlist.html#ga83ca1a25f50834f8e6f8ee1e883a8c6e\">sp_playlist_get_offline_download_completed()</a> method can be used to query progress of the download </dd></dl>\n\n</div>\n</div>\n<a class=\"anchor\" id=\"gaf0e39b5969259d10625eb398af0f3f43\"></a><!-- doxytag: member=\"api.h::sp_playlist_has_pending_changes\" ref=\"gaf0e39b5969259d10625eb398af0f3f43\" args=\"(sp_playlist *playlist)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\">bool sp_playlist_has_pending_changes </td>\n          <td>(</td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__types.html#ga1bcf54cbc117a20ab2c15e59eb3a8174\">sp_playlist</a> *&nbsp;</td>\n          <td class=\"paramname\"> <em>playlist</em></td>\n          <td>&nbsp;)&nbsp;</td>\n          <td></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Check if a playlist has pending changes</p>\n<p>Pending changes are local changes that have not yet been acknowledged by the server.</p>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>playlist</em>&nbsp;</td><td>Playlist object</td></tr>\n  </table>\n  </dd>\n</dl>\n<dl class=\"return\"><dt><b>Returns:</b></dt><dd>A flag representing if there are pending changes or not </dd></dl>\n\n</div>\n</div>\n<a class=\"anchor\" id=\"ga8ad160f654f02f13690568070dd57353\"></a><!-- doxytag: member=\"api.h::sp_playlist_is_collaborative\" ref=\"ga8ad160f654f02f13690568070dd57353\" args=\"(sp_playlist *playlist)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\">bool sp_playlist_is_collaborative </td>\n          <td>(</td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__types.html#ga1bcf54cbc117a20ab2c15e59eb3a8174\">sp_playlist</a> *&nbsp;</td>\n          <td class=\"paramname\"> <em>playlist</em></td>\n          <td>&nbsp;)&nbsp;</td>\n          <td></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Return collaborative status for a playlist.</p>\n<p>A playlist in collaborative state can be modifed by all users, not only the user owning the list</p>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>playlist</em>&nbsp;</td><td>Playlist object</td></tr>\n  </table>\n  </dd>\n</dl>\n<dl class=\"return\"><dt><b>Returns:</b></dt><dd>true if playlist is collaborative, otherwise false </dd></dl>\n\n</div>\n</div>\n<a class=\"anchor\" id=\"ga28456d1242693c6d890516dc782ab3ec\"></a><!-- doxytag: member=\"api.h::sp_playlist_is_in_ram\" ref=\"ga28456d1242693c6d890516dc782ab3ec\" args=\"(sp_session *session, sp_playlist *playlist)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\">bool sp_playlist_is_in_ram </td>\n          <td>(</td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__types.html#ga70dd19c6f824cf6a159575aa4c128b53\">sp_session</a> *&nbsp;</td>\n          <td class=\"paramname\"> <em>session</em>, </td>\n        </tr>\n        <tr>\n          <td class=\"paramkey\"></td>\n          <td></td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__types.html#ga1bcf54cbc117a20ab2c15e59eb3a8174\">sp_playlist</a> *&nbsp;</td>\n          <td class=\"paramname\"> <em>playlist</em></td><td>&nbsp;</td>\n        </tr>\n        <tr>\n          <td></td>\n          <td>)</td>\n          <td></td><td></td><td></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Return whether a playlist is loaded in RAM (as opposed to only stored on disk)</p>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>session</em>&nbsp;</td><td>Session object </td></tr>\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>playlist</em>&nbsp;</td><td>Playlist object</td></tr>\n  </table>\n  </dd>\n</dl>\n<dl class=\"return\"><dt><b>Returns:</b></dt><dd>True iff playlist is in RAM, False otherwise</dd></dl>\n<dl class=\"note\"><dt><b>Note:</b></dt><dd>When a playlist is no longer in RAM it will appear empty. However, libspotify will retain information about the list metadata (owner, title, picture, etc) in RAM. There is one caveat tough: If libspotify has never seen the playlist before this metadata will also be unset. In order for libspotify to get the metadata the playlist needs to be loaded at least once. In order words, if libspotify starts with an empty playlist cache and the application has set 'initially_unload_playlists' config parameter to True all playlists will be empty. It will not be possible to generate URI's to the playlists nor extract playlist title until the application calls sp_playlist_set_in_ram(..., true). So an application that needs to stay within a low memory profile would need to cycle thru all new playlists in order to extract metadata.</dd></dl>\n<p>The easiest way to detect this case is when <a class=\"el\" href=\"group__playlist.html#ga28456d1242693c6d890516dc782ab3ec\">sp_playlist_is_in_ram()</a> returns false and <a class=\"el\" href=\"group__link.html#ga805392bfa8e526eebedc1cf5a7bcae0f\">sp_link_create_from_playlist()</a> returns NULL </p>\n\n</div>\n</div>\n<a class=\"anchor\" id=\"gaee8ea6c07dfdca3397e27b278fa4870a\"></a><!-- doxytag: member=\"api.h::sp_playlist_is_loaded\" ref=\"gaee8ea6c07dfdca3397e27b278fa4870a\" args=\"(sp_playlist *playlist)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\">bool sp_playlist_is_loaded </td>\n          <td>(</td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__types.html#ga1bcf54cbc117a20ab2c15e59eb3a8174\">sp_playlist</a> *&nbsp;</td>\n          <td class=\"paramname\"> <em>playlist</em></td>\n          <td>&nbsp;)&nbsp;</td>\n          <td></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Get load status for the specified playlist. If it's false, you have to wait until playlist_state_changed happens, and check again if is_loaded has changed</p>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>playlist</em>&nbsp;</td><td>Playlist object</td></tr>\n  </table>\n  </dd>\n</dl>\n<dl class=\"return\"><dt><b>Returns:</b></dt><dd>True if playlist is loaded, otherwise false </dd></dl>\n<dl><dt><b>Examples: </b></dt><dd><a class=\"el\" href=\"browse_8c-example.html#a37\">browse.c</a>.</dd>\n</dl>\n</div>\n</div>\n<a class=\"anchor\" id=\"ga61b7e33cc1aedb4e31a2af75ae0ac8cc\"></a><!-- doxytag: member=\"api.h::sp_playlist_name\" ref=\"ga61b7e33cc1aedb4e31a2af75ae0ac8cc\" args=\"(sp_playlist *playlist)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\">const char* sp_playlist_name </td>\n          <td>(</td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__types.html#ga1bcf54cbc117a20ab2c15e59eb3a8174\">sp_playlist</a> *&nbsp;</td>\n          <td class=\"paramname\"> <em>playlist</em></td>\n          <td>&nbsp;)&nbsp;</td>\n          <td></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Return name of given playlist</p>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>playlist</em>&nbsp;</td><td>Playlist object</td></tr>\n  </table>\n  </dd>\n</dl>\n<dl class=\"return\"><dt><b>Returns:</b></dt><dd>The name of the given playlist </dd></dl>\n<dl><dt><b>Examples: </b></dt><dd><a class=\"el\" href=\"browse_8c-example.html#a43\">browse.c</a>, and <a class=\"el\" href=\"jukebox_8c-example.html#a8\">jukebox.c</a>.</dd>\n</dl>\n</div>\n</div>\n<a class=\"anchor\" id=\"ga967ad87f0db702513ecda82546f667c5\"></a><!-- doxytag: member=\"api.h::sp_playlist_num_subscribers\" ref=\"ga967ad87f0db702513ecda82546f667c5\" args=\"(sp_playlist *playlist)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\">unsigned int sp_playlist_num_subscribers </td>\n          <td>(</td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__types.html#ga1bcf54cbc117a20ab2c15e59eb3a8174\">sp_playlist</a> *&nbsp;</td>\n          <td class=\"paramname\"> <em>playlist</em></td>\n          <td>&nbsp;)&nbsp;</td>\n          <td></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Return number of subscribers for a given playlist</p>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>playlist</em>&nbsp;</td><td>Playlist object</td></tr>\n  </table>\n  </dd>\n</dl>\n<dl class=\"return\"><dt><b>Returns:</b></dt><dd>Number of subscribers </dd></dl>\n\n</div>\n</div>\n<a class=\"anchor\" id=\"ga684a3acc60f99b3b26488ed813ee5d23\"></a><!-- doxytag: member=\"api.h::sp_playlist_num_tracks\" ref=\"ga684a3acc60f99b3b26488ed813ee5d23\" args=\"(sp_playlist *playlist)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\">int sp_playlist_num_tracks </td>\n          <td>(</td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__types.html#ga1bcf54cbc117a20ab2c15e59eb3a8174\">sp_playlist</a> *&nbsp;</td>\n          <td class=\"paramname\"> <em>playlist</em></td>\n          <td>&nbsp;)&nbsp;</td>\n          <td></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Return number of tracks in the given playlist</p>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>playlist</em>&nbsp;</td><td>Playlist object</td></tr>\n  </table>\n  </dd>\n</dl>\n<dl class=\"return\"><dt><b>Returns:</b></dt><dd>The number of tracks in the playlist </dd></dl>\n<dl><dt><b>Examples: </b></dt><dd><a class=\"el\" href=\"browse_8c-example.html#a38\">browse.c</a>, and <a class=\"el\" href=\"jukebox_8c-example.html#a0\">jukebox.c</a>.</dd>\n</dl>\n</div>\n</div>\n<a class=\"anchor\" id=\"gac3e4295d3353eb9998402aedfdbd55de\"></a><!-- doxytag: member=\"api.h::sp_playlist_owner\" ref=\"gac3e4295d3353eb9998402aedfdbd55de\" args=\"(sp_playlist *playlist)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\"><a class=\"el\" href=\"group__types.html#gaed2dbaa1eebd6752f76613daad9158bc\">sp_user</a>* sp_playlist_owner </td>\n          <td>(</td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__types.html#ga1bcf54cbc117a20ab2c15e59eb3a8174\">sp_playlist</a> *&nbsp;</td>\n          <td class=\"paramname\"> <em>playlist</em></td>\n          <td>&nbsp;)&nbsp;</td>\n          <td></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Return a pointer to the user for the given playlist</p>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>playlist</em>&nbsp;</td><td>Playlist object</td></tr>\n  </table>\n  </dd>\n</dl>\n<dl class=\"return\"><dt><b>Returns:</b></dt><dd>User object </dd></dl>\n\n</div>\n</div>\n<a class=\"anchor\" id=\"gacb9250eb530869b039541a8b62dfab6c\"></a><!-- doxytag: member=\"api.h::sp_playlist_release\" ref=\"gacb9250eb530869b039541a8b62dfab6c\" args=\"(sp_playlist *playlist)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\"><a class=\"el\" href=\"group__error.html#gafd27986ce4cd9eeaeca8adda83c9eb6b\">sp_error</a> sp_playlist_release </td>\n          <td>(</td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__types.html#ga1bcf54cbc117a20ab2c15e59eb3a8174\">sp_playlist</a> *&nbsp;</td>\n          <td class=\"paramname\"> <em>playlist</em></td>\n          <td>&nbsp;)&nbsp;</td>\n          <td></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Decrease the reference count of a playlist</p>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>playlist</em>&nbsp;</td><td>The playlist object </td></tr>\n  </table>\n  </dd>\n</dl>\n<dl class=\"return\"><dt><b>Returns:</b></dt><dd>One of the following errors, from <a class=\"el\" href=\"group__error.html#ga83154178d3a32668658734d2facfa22b\">sp_error</a> SP_ERROR_OK </dd></dl>\n<dl><dt><b>Examples: </b></dt><dd><a class=\"el\" href=\"browse_8c-example.html#a42\">browse.c</a>.</dd>\n</dl>\n</div>\n</div>\n<a class=\"anchor\" id=\"ga7fcbf909a0fa8bf25f0b1d1e7dd0e160\"></a><!-- doxytag: member=\"api.h::sp_playlist_remove_callbacks\" ref=\"ga7fcbf909a0fa8bf25f0b1d1e7dd0e160\" args=\"(sp_playlist *playlist, sp_playlist_callbacks *callbacks, void *userdata)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\"><a class=\"el\" href=\"group__error.html#gafd27986ce4cd9eeaeca8adda83c9eb6b\">sp_error</a> sp_playlist_remove_callbacks </td>\n          <td>(</td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__types.html#ga1bcf54cbc117a20ab2c15e59eb3a8174\">sp_playlist</a> *&nbsp;</td>\n          <td class=\"paramname\"> <em>playlist</em>, </td>\n        </tr>\n        <tr>\n          <td class=\"paramkey\"></td>\n          <td></td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"structsp__playlist__callbacks.html\">sp_playlist_callbacks</a> *&nbsp;</td>\n          <td class=\"paramname\"> <em>callbacks</em>, </td>\n        </tr>\n        <tr>\n          <td class=\"paramkey\"></td>\n          <td></td>\n          <td class=\"paramtype\">void *&nbsp;</td>\n          <td class=\"paramname\"> <em>userdata</em></td><td>&nbsp;</td>\n        </tr>\n        <tr>\n          <td></td>\n          <td>)</td>\n          <td></td><td></td><td></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Unregister interest in the given playlist</p>\n<p>The combination of (<code>callbacks</code>, <code>userdata</code>) is used to find the entry to be removed</p>\n<p>Here is a snippet from <code>jukebox.c:</code>  <div class=\"fragment\"><pre class=\"fragment\">    <a class=\"code\" href=\"group__playlist.html#ga7fcbf909a0fa8bf25f0b1d1e7dd0e160\">sp_playlist_remove_callbacks</a>(pl, &amp;pl_callbacks, NULL);\n</pre></div></p>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>playlist</em>&nbsp;</td><td>Playlist object </td></tr>\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>callbacks</em>&nbsp;</td><td>Callbacks, see <a class=\"el\" href=\"structsp__playlist__callbacks.html\">sp_playlist_callbacks</a> </td></tr>\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>userdata</em>&nbsp;</td><td>Userdata to be passed to callbacks </td></tr>\n  </table>\n  </dd>\n</dl>\n<dl class=\"see\"><dt><b>See also:</b></dt><dd><a class=\"el\" href=\"group__playlist.html#gab15fca12d387c69b4998a4d2b48e5b32\">sp_playlist_add_callbacks</a> </dd></dl>\n<dl class=\"return\"><dt><b>Returns:</b></dt><dd>One of the following errors, from <a class=\"el\" href=\"group__error.html#ga83154178d3a32668658734d2facfa22b\">sp_error</a> SP_ERROR_OK </dd></dl>\n<dl><dt><b>Examples: </b></dt><dd><a class=\"el\" href=\"browse_8c-example.html#a41\">browse.c</a>, and <a class=\"el\" href=\"jukebox_8c-example.html#a11\">jukebox.c</a>.</dd>\n</dl>\n</div>\n</div>\n<a class=\"anchor\" id=\"gabd62cd7ff9484b4c31ff7f159ec41b6a\"></a><!-- doxytag: member=\"api.h::sp_playlist_remove_tracks\" ref=\"gabd62cd7ff9484b4c31ff7f159ec41b6a\" args=\"(sp_playlist *playlist, const int *tracks, int num_tracks)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\"><a class=\"el\" href=\"group__error.html#gafd27986ce4cd9eeaeca8adda83c9eb6b\">sp_error</a> sp_playlist_remove_tracks </td>\n          <td>(</td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__types.html#ga1bcf54cbc117a20ab2c15e59eb3a8174\">sp_playlist</a> *&nbsp;</td>\n          <td class=\"paramname\"> <em>playlist</em>, </td>\n        </tr>\n        <tr>\n          <td class=\"paramkey\"></td>\n          <td></td>\n          <td class=\"paramtype\">const int *&nbsp;</td>\n          <td class=\"paramname\"> <em>tracks</em>, </td>\n        </tr>\n        <tr>\n          <td class=\"paramkey\"></td>\n          <td></td>\n          <td class=\"paramtype\">int&nbsp;</td>\n          <td class=\"paramname\"> <em>num_tracks</em></td><td>&nbsp;</td>\n        </tr>\n        <tr>\n          <td></td>\n          <td>)</td>\n          <td></td><td></td><td></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Remove tracks from a playlist</p>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>playlist</em>&nbsp;</td><td>Playlist object </td></tr>\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>tracks</em>&nbsp;</td><td>Array of pointer to track indices. A certain track index should be present at most once, e.g. [0, 1, 2] is valid indata, whereas [0, 1, 1] is invalid. </td></tr>\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>num_tracks</em>&nbsp;</td><td>Length of <code>tracks</code> array</td></tr>\n  </table>\n  </dd>\n</dl>\n<dl class=\"return\"><dt><b>Returns:</b></dt><dd>One of the following errors, from <a class=\"el\" href=\"group__error.html#ga83154178d3a32668658734d2facfa22b\">sp_error</a> SP_ERROR_OK SP_ERROR_PERMISSION_DENIED </dd></dl>\n<dl><dt><b>Examples: </b></dt><dd><a class=\"el\" href=\"jukebox_8c-example.html#a23\">jukebox.c</a>.</dd>\n</dl>\n</div>\n</div>\n<a class=\"anchor\" id=\"gad6c3880c514353e204fdd90830b516ec\"></a><!-- doxytag: member=\"api.h::sp_playlist_rename\" ref=\"gad6c3880c514353e204fdd90830b516ec\" args=\"(sp_playlist *playlist, const char *new_name)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\"><a class=\"el\" href=\"group__error.html#gafd27986ce4cd9eeaeca8adda83c9eb6b\">sp_error</a> sp_playlist_rename </td>\n          <td>(</td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__types.html#ga1bcf54cbc117a20ab2c15e59eb3a8174\">sp_playlist</a> *&nbsp;</td>\n          <td class=\"paramname\"> <em>playlist</em>, </td>\n        </tr>\n        <tr>\n          <td class=\"paramkey\"></td>\n          <td></td>\n          <td class=\"paramtype\">const char *&nbsp;</td>\n          <td class=\"paramname\"> <em>new_name</em></td><td>&nbsp;</td>\n        </tr>\n        <tr>\n          <td></td>\n          <td>)</td>\n          <td></td><td></td><td></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Rename the given playlist The name must not consist of only spaces and it must be shorter than 256 characters.</p>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>playlist</em>&nbsp;</td><td>Playlist object </td></tr>\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>new_name</em>&nbsp;</td><td>New name for playlist</td></tr>\n  </table>\n  </dd>\n</dl>\n<dl class=\"return\"><dt><b>Returns:</b></dt><dd>One of the following errors, from <a class=\"el\" href=\"group__error.html#ga83154178d3a32668658734d2facfa22b\">sp_error</a> SP_ERROR_OK SP_ERROR_INVALID_INDATA SP_ERROR_PERMISSION_DENIED </dd></dl>\n\n</div>\n</div>\n<a class=\"anchor\" id=\"ga90ffd8c9fc6abc7375e89f4cb49adb11\"></a><!-- doxytag: member=\"api.h::sp_playlist_reorder_tracks\" ref=\"ga90ffd8c9fc6abc7375e89f4cb49adb11\" args=\"(sp_playlist *playlist, const int *tracks, int num_tracks, int new_position)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\"><a class=\"el\" href=\"group__error.html#gafd27986ce4cd9eeaeca8adda83c9eb6b\">sp_error</a> sp_playlist_reorder_tracks </td>\n          <td>(</td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__types.html#ga1bcf54cbc117a20ab2c15e59eb3a8174\">sp_playlist</a> *&nbsp;</td>\n          <td class=\"paramname\"> <em>playlist</em>, </td>\n        </tr>\n        <tr>\n          <td class=\"paramkey\"></td>\n          <td></td>\n          <td class=\"paramtype\">const int *&nbsp;</td>\n          <td class=\"paramname\"> <em>tracks</em>, </td>\n        </tr>\n        <tr>\n          <td class=\"paramkey\"></td>\n          <td></td>\n          <td class=\"paramtype\">int&nbsp;</td>\n          <td class=\"paramname\"> <em>num_tracks</em>, </td>\n        </tr>\n        <tr>\n          <td class=\"paramkey\"></td>\n          <td></td>\n          <td class=\"paramtype\">int&nbsp;</td>\n          <td class=\"paramname\"> <em>new_position</em></td><td>&nbsp;</td>\n        </tr>\n        <tr>\n          <td></td>\n          <td>)</td>\n          <td></td><td></td><td></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Move tracks in playlist</p>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>playlist</em>&nbsp;</td><td>Playlist object </td></tr>\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>tracks</em>&nbsp;</td><td>Array of pointer to track indices to be moved. A certain track index should be present at most once, e.g. [0, 1, 2] is valid indata, whereas [0, 1, 1] is invalid. </td></tr>\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>num_tracks</em>&nbsp;</td><td>Length of <code>tracks</code> array </td></tr>\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>new_position</em>&nbsp;</td><td>New position for tracks</td></tr>\n  </table>\n  </dd>\n</dl>\n<dl class=\"return\"><dt><b>Returns:</b></dt><dd>One of the following errors, from <a class=\"el\" href=\"group__error.html#ga83154178d3a32668658734d2facfa22b\">sp_error</a> SP_ERROR_OK SP_ERROR_INVALID_INDATA - position is &gt; current playlist length SP_ERROR_PERMISSION_DENIED </dd></dl>\n\n</div>\n</div>\n<a class=\"anchor\" id=\"ga0bde47f340e0cd590a78007c6af69307\"></a><!-- doxytag: member=\"api.h::sp_playlist_set_autolink_tracks\" ref=\"ga0bde47f340e0cd590a78007c6af69307\" args=\"(sp_playlist *playlist, bool link)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\"><a class=\"el\" href=\"group__error.html#gafd27986ce4cd9eeaeca8adda83c9eb6b\">sp_error</a> sp_playlist_set_autolink_tracks </td>\n          <td>(</td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__types.html#ga1bcf54cbc117a20ab2c15e59eb3a8174\">sp_playlist</a> *&nbsp;</td>\n          <td class=\"paramname\"> <em>playlist</em>, </td>\n        </tr>\n        <tr>\n          <td class=\"paramkey\"></td>\n          <td></td>\n          <td class=\"paramtype\">bool&nbsp;</td>\n          <td class=\"paramname\"> <em>link</em></td><td>&nbsp;</td>\n        </tr>\n        <tr>\n          <td></td>\n          <td>)</td>\n          <td></td><td></td><td></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Set autolinking state for a playlist.</p>\n<p>If a playlist is autolinked, unplayable tracks will be made playable by linking them to other Spotify tracks, where possible.</p>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>playlist</em>&nbsp;</td><td>Playlist object </td></tr>\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>link</em>&nbsp;</td><td>True or false </td></tr>\n  </table>\n  </dd>\n</dl>\n<dl class=\"return\"><dt><b>Returns:</b></dt><dd>One of the following errors, from <a class=\"el\" href=\"group__error.html#ga83154178d3a32668658734d2facfa22b\">sp_error</a> SP_ERROR_OK </dd></dl>\n\n</div>\n</div>\n<a class=\"anchor\" id=\"gad15410bcc2ebd986adabda865830bce4\"></a><!-- doxytag: member=\"api.h::sp_playlist_set_collaborative\" ref=\"gad15410bcc2ebd986adabda865830bce4\" args=\"(sp_playlist *playlist, bool collaborative)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\"><a class=\"el\" href=\"group__error.html#gafd27986ce4cd9eeaeca8adda83c9eb6b\">sp_error</a> sp_playlist_set_collaborative </td>\n          <td>(</td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__types.html#ga1bcf54cbc117a20ab2c15e59eb3a8174\">sp_playlist</a> *&nbsp;</td>\n          <td class=\"paramname\"> <em>playlist</em>, </td>\n        </tr>\n        <tr>\n          <td class=\"paramkey\"></td>\n          <td></td>\n          <td class=\"paramtype\">bool&nbsp;</td>\n          <td class=\"paramname\"> <em>collaborative</em></td><td>&nbsp;</td>\n        </tr>\n        <tr>\n          <td></td>\n          <td>)</td>\n          <td></td><td></td><td></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Set collaborative status for a playlist.</p>\n<p>A playlist in collaborative state can be modified by all users, not only the user owning the list</p>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>playlist</em>&nbsp;</td><td>Playlist object </td></tr>\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>collaborative</em>&nbsp;</td><td>True or false </td></tr>\n  </table>\n  </dd>\n</dl>\n<dl class=\"return\"><dt><b>Returns:</b></dt><dd>One of the following errors, from <a class=\"el\" href=\"group__error.html#ga83154178d3a32668658734d2facfa22b\">sp_error</a> SP_ERROR_OK </dd></dl>\n\n</div>\n</div>\n<a class=\"anchor\" id=\"gaf6ca8a349bdd982f6c8dda52ed691017\"></a><!-- doxytag: member=\"api.h::sp_playlist_set_in_ram\" ref=\"gaf6ca8a349bdd982f6c8dda52ed691017\" args=\"(sp_session *session, sp_playlist *playlist, bool in_ram)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\"><a class=\"el\" href=\"group__error.html#gafd27986ce4cd9eeaeca8adda83c9eb6b\">sp_error</a> sp_playlist_set_in_ram </td>\n          <td>(</td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__types.html#ga70dd19c6f824cf6a159575aa4c128b53\">sp_session</a> *&nbsp;</td>\n          <td class=\"paramname\"> <em>session</em>, </td>\n        </tr>\n        <tr>\n          <td class=\"paramkey\"></td>\n          <td></td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__types.html#ga1bcf54cbc117a20ab2c15e59eb3a8174\">sp_playlist</a> *&nbsp;</td>\n          <td class=\"paramname\"> <em>playlist</em>, </td>\n        </tr>\n        <tr>\n          <td class=\"paramkey\"></td>\n          <td></td>\n          <td class=\"paramtype\">bool&nbsp;</td>\n          <td class=\"paramname\"> <em>in_ram</em></td><td>&nbsp;</td>\n        </tr>\n        <tr>\n          <td></td>\n          <td>)</td>\n          <td></td><td></td><td></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Return whether a playlist is loaded in RAM (as opposed to only stored on disk)</p>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>session</em>&nbsp;</td><td>Session object </td></tr>\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>playlist</em>&nbsp;</td><td>Playlist object </td></tr>\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>in_ram</em>&nbsp;</td><td>Controls whether or not to keep the list in RAM </td></tr>\n  </table>\n  </dd>\n</dl>\n<dl class=\"return\"><dt><b>Returns:</b></dt><dd>One of the following errors, from <a class=\"el\" href=\"group__error.html#ga83154178d3a32668658734d2facfa22b\">sp_error</a> SP_ERROR_OK </dd></dl>\n\n</div>\n</div>\n<a class=\"anchor\" id=\"ga784f648f9cc431ef3b51f3491c2f169f\"></a><!-- doxytag: member=\"api.h::sp_playlist_set_offline_mode\" ref=\"ga784f648f9cc431ef3b51f3491c2f169f\" args=\"(sp_session *session, sp_playlist *playlist, bool offline)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\"><a class=\"el\" href=\"group__error.html#gafd27986ce4cd9eeaeca8adda83c9eb6b\">sp_error</a> sp_playlist_set_offline_mode </td>\n          <td>(</td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__types.html#ga70dd19c6f824cf6a159575aa4c128b53\">sp_session</a> *&nbsp;</td>\n          <td class=\"paramname\"> <em>session</em>, </td>\n        </tr>\n        <tr>\n          <td class=\"paramkey\"></td>\n          <td></td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__types.html#ga1bcf54cbc117a20ab2c15e59eb3a8174\">sp_playlist</a> *&nbsp;</td>\n          <td class=\"paramname\"> <em>playlist</em>, </td>\n        </tr>\n        <tr>\n          <td class=\"paramkey\"></td>\n          <td></td>\n          <td class=\"paramtype\">bool&nbsp;</td>\n          <td class=\"paramname\"> <em>offline</em></td><td>&nbsp;</td>\n        </tr>\n        <tr>\n          <td></td>\n          <td>)</td>\n          <td></td><td></td><td></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Mark a playlist to be synchronized for offline playback. The playlist must be in the users playlistcontainer</p>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>session</em>&nbsp;</td><td>Session object </td></tr>\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>playlist</em>&nbsp;</td><td>Playlist object </td></tr>\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>offline</em>&nbsp;</td><td>True iff playlist should be offline, false otherwise </td></tr>\n  </table>\n  </dd>\n</dl>\n<dl class=\"return\"><dt><b>Returns:</b></dt><dd>One of the following errors, from <a class=\"el\" href=\"group__error.html#ga83154178d3a32668658734d2facfa22b\">sp_error</a> SP_ERROR_OK </dd></dl>\n\n</div>\n</div>\n<a class=\"anchor\" id=\"gad49f491babc475f8d4aeea1b4452ff8b\"></a><!-- doxytag: member=\"api.h::sp_playlist_subscribers\" ref=\"gad49f491babc475f8d4aeea1b4452ff8b\" args=\"(sp_playlist *playlist)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\"><a class=\"el\" href=\"structsp__subscribers.html\">sp_subscribers</a>* sp_playlist_subscribers </td>\n          <td>(</td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__types.html#ga1bcf54cbc117a20ab2c15e59eb3a8174\">sp_playlist</a> *&nbsp;</td>\n          <td class=\"paramname\"> <em>playlist</em></td>\n          <td>&nbsp;)&nbsp;</td>\n          <td></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Return subscribers for a playlist</p>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>playlist</em>&nbsp;</td><td>Playlist object</td></tr>\n  </table>\n  </dd>\n</dl>\n<dl class=\"return\"><dt><b>Returns:</b></dt><dd><a class=\"el\" href=\"structsp__subscribers.html\">sp_subscribers</a> struct with array of canonical usernames. This object should be free'd using <a class=\"el\" href=\"group__playlist.html#gae7754b74b1c3c8f5222ca43b6608ce6a\">sp_playlist_subscribers_free()</a></dd></dl>\n<dl class=\"note\"><dt><b>Note:</b></dt><dd>The count returned for this function may be less than those returned by <a class=\"el\" href=\"group__playlist.html#ga967ad87f0db702513ecda82546f667c5\">sp_playlist_num_subscribers()</a>. Spotify does not track each user subscribed to a playlist for playlist with many (&gt;500) subscribers. </dd></dl>\n\n</div>\n</div>\n<a class=\"anchor\" id=\"gae7754b74b1c3c8f5222ca43b6608ce6a\"></a><!-- doxytag: member=\"api.h::sp_playlist_subscribers_free\" ref=\"gae7754b74b1c3c8f5222ca43b6608ce6a\" args=\"(sp_subscribers *subscribers)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\"><a class=\"el\" href=\"group__error.html#gafd27986ce4cd9eeaeca8adda83c9eb6b\">sp_error</a> sp_playlist_subscribers_free </td>\n          <td>(</td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"structsp__subscribers.html\">sp_subscribers</a> *&nbsp;</td>\n          <td class=\"paramname\"> <em>subscribers</em></td>\n          <td>&nbsp;)&nbsp;</td>\n          <td></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Free object returned from <a class=\"el\" href=\"group__playlist.html#gad49f491babc475f8d4aeea1b4452ff8b\">sp_playlist_subscribers()</a></p>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>subscribers</em>&nbsp;</td><td>Subscribers object </td></tr>\n  </table>\n  </dd>\n</dl>\n<dl class=\"return\"><dt><b>Returns:</b></dt><dd>One of the following errors, from <a class=\"el\" href=\"group__error.html#ga83154178d3a32668658734d2facfa22b\">sp_error</a> SP_ERROR_OK </dd></dl>\n\n</div>\n</div>\n<a class=\"anchor\" id=\"ga7a03854fe6072476306780d23c6cac16\"></a><!-- doxytag: member=\"api.h::sp_playlist_track\" ref=\"ga7a03854fe6072476306780d23c6cac16\" args=\"(sp_playlist *playlist, int index)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\"><a class=\"el\" href=\"group__types.html#ga47bbd2262f0c8b5d7147af7d62198e48\">sp_track</a>* sp_playlist_track </td>\n          <td>(</td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__types.html#ga1bcf54cbc117a20ab2c15e59eb3a8174\">sp_playlist</a> *&nbsp;</td>\n          <td class=\"paramname\"> <em>playlist</em>, </td>\n        </tr>\n        <tr>\n          <td class=\"paramkey\"></td>\n          <td></td>\n          <td class=\"paramtype\">int&nbsp;</td>\n          <td class=\"paramname\"> <em>index</em></td><td>&nbsp;</td>\n        </tr>\n        <tr>\n          <td></td>\n          <td>)</td>\n          <td></td><td></td><td></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Return the track at the given index in a playlist</p>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>playlist</em>&nbsp;</td><td>Playlist object </td></tr>\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>index</em>&nbsp;</td><td>Index into playlist container. Should be in the interval [0, <a class=\"el\" href=\"group__playlist.html#ga684a3acc60f99b3b26488ed813ee5d23\">sp_playlist_num_tracks()</a> - 1]</td></tr>\n  </table>\n  </dd>\n</dl>\n<dl class=\"return\"><dt><b>Returns:</b></dt><dd>The track at the given index </dd></dl>\n<dl><dt><b>Examples: </b></dt><dd><a class=\"el\" href=\"browse_8c-example.html#a39\">browse.c</a>, and <a class=\"el\" href=\"jukebox_8c-example.html#a1\">jukebox.c</a>.</dd>\n</dl>\n</div>\n</div>\n<a class=\"anchor\" id=\"gab8e77f8d63e787f8aa1a066d74daa74c\"></a><!-- doxytag: member=\"api.h::sp_playlist_track_create_time\" ref=\"gab8e77f8d63e787f8aa1a066d74daa74c\" args=\"(sp_playlist *playlist, int index)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\">int sp_playlist_track_create_time </td>\n          <td>(</td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__types.html#ga1bcf54cbc117a20ab2c15e59eb3a8174\">sp_playlist</a> *&nbsp;</td>\n          <td class=\"paramname\"> <em>playlist</em>, </td>\n        </tr>\n        <tr>\n          <td class=\"paramkey\"></td>\n          <td></td>\n          <td class=\"paramtype\">int&nbsp;</td>\n          <td class=\"paramname\"> <em>index</em></td><td>&nbsp;</td>\n        </tr>\n        <tr>\n          <td></td>\n          <td>)</td>\n          <td></td><td></td><td></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Return when the given index was added to the playlist</p>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>playlist</em>&nbsp;</td><td>Playlist object </td></tr>\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>index</em>&nbsp;</td><td>Index into playlist container. Should be in the interval [0, <a class=\"el\" href=\"group__playlist.html#ga684a3acc60f99b3b26488ed813ee5d23\">sp_playlist_num_tracks()</a> - 1]</td></tr>\n  </table>\n  </dd>\n</dl>\n<dl class=\"return\"><dt><b>Returns:</b></dt><dd>Time, Seconds since unix epoch. </dd></dl>\n\n</div>\n</div>\n<a class=\"anchor\" id=\"ga80fcd9e7b40c791433c07d66e2ad432a\"></a><!-- doxytag: member=\"api.h::sp_playlist_track_creator\" ref=\"ga80fcd9e7b40c791433c07d66e2ad432a\" args=\"(sp_playlist *playlist, int index)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\"><a class=\"el\" href=\"group__types.html#gaed2dbaa1eebd6752f76613daad9158bc\">sp_user</a>* sp_playlist_track_creator </td>\n          <td>(</td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__types.html#ga1bcf54cbc117a20ab2c15e59eb3a8174\">sp_playlist</a> *&nbsp;</td>\n          <td class=\"paramname\"> <em>playlist</em>, </td>\n        </tr>\n        <tr>\n          <td class=\"paramkey\"></td>\n          <td></td>\n          <td class=\"paramtype\">int&nbsp;</td>\n          <td class=\"paramname\"> <em>index</em></td><td>&nbsp;</td>\n        </tr>\n        <tr>\n          <td></td>\n          <td>)</td>\n          <td></td><td></td><td></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Return user that added the given index in the playlist</p>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>playlist</em>&nbsp;</td><td>Playlist object </td></tr>\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>index</em>&nbsp;</td><td>Index into playlist container. Should be in the interval [0, <a class=\"el\" href=\"group__playlist.html#ga684a3acc60f99b3b26488ed813ee5d23\">sp_playlist_num_tracks()</a> - 1]</td></tr>\n  </table>\n  </dd>\n</dl>\n<dl class=\"return\"><dt><b>Returns:</b></dt><dd>User object </dd></dl>\n\n</div>\n</div>\n<a class=\"anchor\" id=\"ga6887b9dabb30a060b10bdb75f8b3f971\"></a><!-- doxytag: member=\"api.h::sp_playlist_track_message\" ref=\"ga6887b9dabb30a060b10bdb75f8b3f971\" args=\"(sp_playlist *playlist, int index)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\">const char* sp_playlist_track_message </td>\n          <td>(</td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__types.html#ga1bcf54cbc117a20ab2c15e59eb3a8174\">sp_playlist</a> *&nbsp;</td>\n          <td class=\"paramname\"> <em>playlist</em>, </td>\n        </tr>\n        <tr>\n          <td class=\"paramkey\"></td>\n          <td></td>\n          <td class=\"paramtype\">int&nbsp;</td>\n          <td class=\"paramname\"> <em>index</em></td><td>&nbsp;</td>\n        </tr>\n        <tr>\n          <td></td>\n          <td>)</td>\n          <td></td><td></td><td></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Return a message attached to a playlist item. Typically used on inbox.</p>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>playlist</em>&nbsp;</td><td>Playlist object </td></tr>\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>index</em>&nbsp;</td><td>Index into playlist container. Should be in the interval [0, <a class=\"el\" href=\"group__playlist.html#ga684a3acc60f99b3b26488ed813ee5d23\">sp_playlist_num_tracks()</a> - 1]</td></tr>\n  </table>\n  </dd>\n</dl>\n<dl class=\"return\"><dt><b>Returns:</b></dt><dd>UTF-8 encoded message, or NULL if no message is present </dd></dl>\n\n</div>\n</div>\n<a class=\"anchor\" id=\"gab9e00ee5bc6b5dc0b3d58cbdb32c0c7b\"></a><!-- doxytag: member=\"api.h::sp_playlist_track_seen\" ref=\"gab9e00ee5bc6b5dc0b3d58cbdb32c0c7b\" args=\"(sp_playlist *playlist, int index)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\">bool sp_playlist_track_seen </td>\n          <td>(</td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__types.html#ga1bcf54cbc117a20ab2c15e59eb3a8174\">sp_playlist</a> *&nbsp;</td>\n          <td class=\"paramname\"> <em>playlist</em>, </td>\n        </tr>\n        <tr>\n          <td class=\"paramkey\"></td>\n          <td></td>\n          <td class=\"paramtype\">int&nbsp;</td>\n          <td class=\"paramname\"> <em>index</em></td><td>&nbsp;</td>\n        </tr>\n        <tr>\n          <td></td>\n          <td>)</td>\n          <td></td><td></td><td></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Return if a playlist entry is marked as seen or not</p>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>playlist</em>&nbsp;</td><td>Playlist object </td></tr>\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>index</em>&nbsp;</td><td>Index into playlist container. Should be in the interval [0, <a class=\"el\" href=\"group__playlist.html#ga684a3acc60f99b3b26488ed813ee5d23\">sp_playlist_num_tracks()</a> - 1]</td></tr>\n  </table>\n  </dd>\n</dl>\n<dl class=\"return\"><dt><b>Returns:</b></dt><dd>Seen state </dd></dl>\n\n</div>\n</div>\n<a class=\"anchor\" id=\"ga69f5cc1bdd7dbdcdb476a7b1d2b7834d\"></a><!-- doxytag: member=\"api.h::sp_playlist_track_set_seen\" ref=\"ga69f5cc1bdd7dbdcdb476a7b1d2b7834d\" args=\"(sp_playlist *playlist, int index, bool seen)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\"><a class=\"el\" href=\"group__error.html#gafd27986ce4cd9eeaeca8adda83c9eb6b\">sp_error</a> sp_playlist_track_set_seen </td>\n          <td>(</td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__types.html#ga1bcf54cbc117a20ab2c15e59eb3a8174\">sp_playlist</a> *&nbsp;</td>\n          <td class=\"paramname\"> <em>playlist</em>, </td>\n        </tr>\n        <tr>\n          <td class=\"paramkey\"></td>\n          <td></td>\n          <td class=\"paramtype\">int&nbsp;</td>\n          <td class=\"paramname\"> <em>index</em>, </td>\n        </tr>\n        <tr>\n          <td class=\"paramkey\"></td>\n          <td></td>\n          <td class=\"paramtype\">bool&nbsp;</td>\n          <td class=\"paramname\"> <em>seen</em></td><td>&nbsp;</td>\n        </tr>\n        <tr>\n          <td></td>\n          <td>)</td>\n          <td></td><td></td><td></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Set seen status of a playlist entry</p>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>playlist</em>&nbsp;</td><td>Playlist object </td></tr>\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>index</em>&nbsp;</td><td>Index into playlist container. Should be in the interval [0, <a class=\"el\" href=\"group__playlist.html#ga684a3acc60f99b3b26488ed813ee5d23\">sp_playlist_num_tracks()</a> - 1] </td></tr>\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>seen</em>&nbsp;</td><td>Seen status to be set</td></tr>\n  </table>\n  </dd>\n</dl>\n<dl class=\"return\"><dt><b>Returns:</b></dt><dd>error One of the following errors, from <a class=\"el\" href=\"group__error.html#ga83154178d3a32668658734d2facfa22b\">sp_error</a> SP_ERROR_OK SP_ERROR_INDEX_OUT_OF_RANGE </dd></dl>\n\n</div>\n</div>\n<a class=\"anchor\" id=\"ga9ebbf147230b3ca98b68e556cf24e6bd\"></a><!-- doxytag: member=\"api.h::sp_playlist_update_subscribers\" ref=\"ga9ebbf147230b3ca98b68e556cf24e6bd\" args=\"(sp_session *session, sp_playlist *playlist)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\"><a class=\"el\" href=\"group__error.html#gafd27986ce4cd9eeaeca8adda83c9eb6b\">sp_error</a> sp_playlist_update_subscribers </td>\n          <td>(</td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__types.html#ga70dd19c6f824cf6a159575aa4c128b53\">sp_session</a> *&nbsp;</td>\n          <td class=\"paramname\"> <em>session</em>, </td>\n        </tr>\n        <tr>\n          <td class=\"paramkey\"></td>\n          <td></td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__types.html#ga1bcf54cbc117a20ab2c15e59eb3a8174\">sp_playlist</a> *&nbsp;</td>\n          <td class=\"paramname\"> <em>playlist</em></td><td>&nbsp;</td>\n        </tr>\n        <tr>\n          <td></td>\n          <td>)</td>\n          <td></td><td></td><td></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Ask library to update the subscription count for a playlist</p>\n<p>When the subscription info has been fetched from the Spotify backend the playlist subscribers_changed() callback will be invoked. In that callback use <a class=\"el\" href=\"group__playlist.html#ga967ad87f0db702513ecda82546f667c5\">sp_playlist_num_subscribers()</a> and/or <a class=\"el\" href=\"group__playlist.html#gad49f491babc475f8d4aeea1b4452ff8b\">sp_playlist_subscribers()</a> to get information about the subscribers. You can call those two functions anytime you want but the information might not be up to date in such cases</p>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>session</em>&nbsp;</td><td>Session object </td></tr>\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>playlist</em>&nbsp;</td><td>Playlist object </td></tr>\n  </table>\n  </dd>\n</dl>\n<dl class=\"return\"><dt><b>Returns:</b></dt><dd>One of the following errors, from <a class=\"el\" href=\"group__error.html#ga83154178d3a32668658734d2facfa22b\">sp_error</a> SP_ERROR_OK </dd></dl>\n\n</div>\n</div>\n<a class=\"anchor\" id=\"ga1976cb49c391cdd2dbe7c40d1bc71570\"></a><!-- doxytag: member=\"api.h::sp_playlistcontainer_add_callbacks\" ref=\"ga1976cb49c391cdd2dbe7c40d1bc71570\" args=\"(sp_playlistcontainer *pc, sp_playlistcontainer_callbacks *callbacks, void *userdata)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\"><a class=\"el\" href=\"group__error.html#gafd27986ce4cd9eeaeca8adda83c9eb6b\">sp_error</a> sp_playlistcontainer_add_callbacks </td>\n          <td>(</td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__types.html#ga45a2febbe167483e48dab8d606d462d7\">sp_playlistcontainer</a> *&nbsp;</td>\n          <td class=\"paramname\"> <em>pc</em>, </td>\n        </tr>\n        <tr>\n          <td class=\"paramkey\"></td>\n          <td></td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"structsp__playlistcontainer__callbacks.html\">sp_playlistcontainer_callbacks</a> *&nbsp;</td>\n          <td class=\"paramname\"> <em>callbacks</em>, </td>\n        </tr>\n        <tr>\n          <td class=\"paramkey\"></td>\n          <td></td>\n          <td class=\"paramtype\">void *&nbsp;</td>\n          <td class=\"paramname\"> <em>userdata</em></td><td>&nbsp;</td>\n        </tr>\n        <tr>\n          <td></td>\n          <td>)</td>\n          <td></td><td></td><td></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Register interest in changes to a playlist container</p>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>pc</em>&nbsp;</td><td>Playlist container </td></tr>\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>callbacks</em>&nbsp;</td><td>Callbacks, see <a class=\"el\" href=\"structsp__playlistcontainer__callbacks.html\">sp_playlistcontainer_callbacks</a> </td></tr>\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>userdata</em>&nbsp;</td><td>Opaque value passed to callbacks.</td></tr>\n  </table>\n  </dd>\n</dl>\n<dl class=\"note\"><dt><b>Note:</b></dt><dd>Every <a class=\"el\" href=\"group__playlist.html#ga1976cb49c391cdd2dbe7c40d1bc71570\">sp_playlistcontainer_add_callbacks()</a> needs to be paired with a corresponding <a class=\"el\" href=\"group__playlist.html#gafb5242b8f0f9964cec29d32f4d6c1164\">sp_playlistcontainer_remove_callbacks()</a> that is invoked before releasing the last reference you own for the container. In other words, you must make sure to have removed all the callbacks before the container gets destroyed.</dd></dl>\n<dl class=\"see\"><dt><b>See also:</b></dt><dd><a class=\"el\" href=\"group__session.html#ga319767f0b795f1c46a08390b587c5671\">sp_session_playlistcontainer()</a> </dd>\n<dd>\n<a class=\"el\" href=\"group__playlist.html#gafb5242b8f0f9964cec29d32f4d6c1164\">sp_playlistcontainer_remove_callbacks</a> </dd></dl>\n<dl class=\"return\"><dt><b>Returns:</b></dt><dd>One of the following errors, from <a class=\"el\" href=\"group__error.html#ga83154178d3a32668658734d2facfa22b\">sp_error</a> SP_ERROR_OK </dd></dl>\n<dl><dt><b>Examples: </b></dt><dd><a class=\"el\" href=\"jukebox_8c-example.html#a16\">jukebox.c</a>.</dd>\n</dl>\n</div>\n</div>\n<a class=\"anchor\" id=\"ga0862502eea52fc5f2465ebad6fd98796\"></a><!-- doxytag: member=\"api.h::sp_playlistcontainer_add_folder\" ref=\"ga0862502eea52fc5f2465ebad6fd98796\" args=\"(sp_playlistcontainer *pc, int index, const char *name)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\"><a class=\"el\" href=\"group__error.html#gafd27986ce4cd9eeaeca8adda83c9eb6b\">sp_error</a> sp_playlistcontainer_add_folder </td>\n          <td>(</td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__types.html#ga45a2febbe167483e48dab8d606d462d7\">sp_playlistcontainer</a> *&nbsp;</td>\n          <td class=\"paramname\"> <em>pc</em>, </td>\n        </tr>\n        <tr>\n          <td class=\"paramkey\"></td>\n          <td></td>\n          <td class=\"paramtype\">int&nbsp;</td>\n          <td class=\"paramname\"> <em>index</em>, </td>\n        </tr>\n        <tr>\n          <td class=\"paramkey\"></td>\n          <td></td>\n          <td class=\"paramtype\">const char *&nbsp;</td>\n          <td class=\"paramname\"> <em>name</em></td><td>&nbsp;</td>\n        </tr>\n        <tr>\n          <td></td>\n          <td>)</td>\n          <td></td><td></td><td></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Add a playlist folder</p>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>pc</em>&nbsp;</td><td>Playlist container </td></tr>\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>index</em>&nbsp;</td><td>Position of SP_PLAYLIST_TYPE_START_FOLDER entry </td></tr>\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>name</em>&nbsp;</td><td>Name of group</td></tr>\n  </table>\n  </dd>\n</dl>\n<dl class=\"return\"><dt><b>Returns:</b></dt><dd>error One of the following errors, from <a class=\"el\" href=\"group__error.html#ga83154178d3a32668658734d2facfa22b\">sp_error</a> SP_ERROR_OK SP_ERROR_INDEX_OUT_OF_RANGE</dd></dl>\n<dl class=\"note\"><dt><b>Note:</b></dt><dd>This operation will actually create two playlists. One of type SP_PLAYLIST_TYPE_START_FOLDER and immediately following a SP_PLAYLIST_TYPE_END_FOLDER one.</dd></dl>\n<p>To remove a playlist folder both of these must be deleted or the list will be left in an inconsistant state.</p>\n<p>There is no way to rename a playlist folder. Instead you need to remove the folder and recreate it again. </p>\n\n</div>\n</div>\n<a class=\"anchor\" id=\"ga840b82b1074a7ca1c9eacd351bed24c2\"></a><!-- doxytag: member=\"api.h::sp_playlistcontainer_add_new_playlist\" ref=\"ga840b82b1074a7ca1c9eacd351bed24c2\" args=\"(sp_playlistcontainer *pc, const char *name)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\"><a class=\"el\" href=\"group__types.html#ga1bcf54cbc117a20ab2c15e59eb3a8174\">sp_playlist</a>* sp_playlistcontainer_add_new_playlist </td>\n          <td>(</td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__types.html#ga45a2febbe167483e48dab8d606d462d7\">sp_playlistcontainer</a> *&nbsp;</td>\n          <td class=\"paramname\"> <em>pc</em>, </td>\n        </tr>\n        <tr>\n          <td class=\"paramkey\"></td>\n          <td></td>\n          <td class=\"paramtype\">const char *&nbsp;</td>\n          <td class=\"paramname\"> <em>name</em></td><td>&nbsp;</td>\n        </tr>\n        <tr>\n          <td></td>\n          <td>)</td>\n          <td></td><td></td><td></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Add an empty playlist at the end of the playlist container. The name must not consist of only spaces and it must be shorter than 256 characters.</p>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>pc</em>&nbsp;</td><td>Playlist container </td></tr>\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>name</em>&nbsp;</td><td>Name of new playlist</td></tr>\n  </table>\n  </dd>\n</dl>\n<dl class=\"return\"><dt><b>Returns:</b></dt><dd>Pointer to the new playlist. Can be NULL if the operation fails. </dd></dl>\n\n</div>\n</div>\n<a class=\"anchor\" id=\"ga87699479087915b741ceef4eebe69ad8\"></a><!-- doxytag: member=\"api.h::sp_playlistcontainer_add_playlist\" ref=\"ga87699479087915b741ceef4eebe69ad8\" args=\"(sp_playlistcontainer *pc, sp_link *link)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\"><a class=\"el\" href=\"group__types.html#ga1bcf54cbc117a20ab2c15e59eb3a8174\">sp_playlist</a>* sp_playlistcontainer_add_playlist </td>\n          <td>(</td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__types.html#ga45a2febbe167483e48dab8d606d462d7\">sp_playlistcontainer</a> *&nbsp;</td>\n          <td class=\"paramname\"> <em>pc</em>, </td>\n        </tr>\n        <tr>\n          <td class=\"paramkey\"></td>\n          <td></td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__types.html#gaf90a23d6b662c96d52ac19f7f4bc1e39\">sp_link</a> *&nbsp;</td>\n          <td class=\"paramname\"> <em>link</em></td><td>&nbsp;</td>\n        </tr>\n        <tr>\n          <td></td>\n          <td>)</td>\n          <td></td><td></td><td></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Add an existing playlist at the end of the given playlist container</p>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>pc</em>&nbsp;</td><td>Playlist container </td></tr>\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>link</em>&nbsp;</td><td>Link object pointing to a playlist</td></tr>\n  </table>\n  </dd>\n</dl>\n<dl class=\"return\"><dt><b>Returns:</b></dt><dd>Pointer to the new playlist. Will be NULL if the playlist already exists. </dd></dl>\n\n</div>\n</div>\n<a class=\"anchor\" id=\"ga2138c537a6ebcd35a01eea54d0dd1e8f\"></a><!-- doxytag: member=\"api.h::sp_playlistcontainer_add_ref\" ref=\"ga2138c537a6ebcd35a01eea54d0dd1e8f\" args=\"(sp_playlistcontainer *pc)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\"><a class=\"el\" href=\"group__error.html#gafd27986ce4cd9eeaeca8adda83c9eb6b\">sp_error</a> sp_playlistcontainer_add_ref </td>\n          <td>(</td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__types.html#ga45a2febbe167483e48dab8d606d462d7\">sp_playlistcontainer</a> *&nbsp;</td>\n          <td class=\"paramname\"> <em>pc</em></td>\n          <td>&nbsp;)&nbsp;</td>\n          <td></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Increase reference count on playlistconatiner object</p>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>pc</em>&nbsp;</td><td>Playlist container. </td></tr>\n  </table>\n  </dd>\n</dl>\n<dl class=\"return\"><dt><b>Returns:</b></dt><dd>One of the following errors, from <a class=\"el\" href=\"group__error.html#ga83154178d3a32668658734d2facfa22b\">sp_error</a> SP_ERROR_OK </dd></dl>\n\n</div>\n</div>\n<a class=\"anchor\" id=\"gadaad604c35e543363e1dd5b23c462db0\"></a><!-- doxytag: member=\"api.h::sp_playlistcontainer_clear_unseen_tracks\" ref=\"gadaad604c35e543363e1dd5b23c462db0\" args=\"(sp_playlistcontainer *pc, sp_playlist *playlist)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\">int sp_playlistcontainer_clear_unseen_tracks </td>\n          <td>(</td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__types.html#ga45a2febbe167483e48dab8d606d462d7\">sp_playlistcontainer</a> *&nbsp;</td>\n          <td class=\"paramname\"> <em>pc</em>, </td>\n        </tr>\n        <tr>\n          <td class=\"paramkey\"></td>\n          <td></td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__types.html#ga1bcf54cbc117a20ab2c15e59eb3a8174\">sp_playlist</a> *&nbsp;</td>\n          <td class=\"paramname\"> <em>playlist</em></td><td>&nbsp;</td>\n        </tr>\n        <tr>\n          <td></td>\n          <td>)</td>\n          <td></td><td></td><td></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Clears a playlist from unseen tracks, so that next call to <a class=\"el\" href=\"group__playlist.html#gad9e11b45843ee4a147b43038a2e55f13\">sp_playlistcontainer_get_unseen_tracks()</a> will return 0 until a new track is added to the <code>playslist</code>.</p>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>pc</em>&nbsp;</td><td>Playlist container. </td></tr>\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>playlist</em>&nbsp;</td><td>Playlist object. </td></tr>\n  </table>\n  </dd>\n</dl>\n<dl class=\"return\"><dt><b>Returns:</b></dt><dd>Returns 0 on success and -1 on failure. </dd></dl>\n\n</div>\n</div>\n<a class=\"anchor\" id=\"gad9e11b45843ee4a147b43038a2e55f13\"></a><!-- doxytag: member=\"api.h::sp_playlistcontainer_get_unseen_tracks\" ref=\"gad9e11b45843ee4a147b43038a2e55f13\" args=\"(sp_playlistcontainer *pc, sp_playlist *playlist, sp_track **tracks, int num_tracks)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\">int sp_playlistcontainer_get_unseen_tracks </td>\n          <td>(</td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__types.html#ga45a2febbe167483e48dab8d606d462d7\">sp_playlistcontainer</a> *&nbsp;</td>\n          <td class=\"paramname\"> <em>pc</em>, </td>\n        </tr>\n        <tr>\n          <td class=\"paramkey\"></td>\n          <td></td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__types.html#ga1bcf54cbc117a20ab2c15e59eb3a8174\">sp_playlist</a> *&nbsp;</td>\n          <td class=\"paramname\"> <em>playlist</em>, </td>\n        </tr>\n        <tr>\n          <td class=\"paramkey\"></td>\n          <td></td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__types.html#ga47bbd2262f0c8b5d7147af7d62198e48\">sp_track</a> **&nbsp;</td>\n          <td class=\"paramname\"> <em>tracks</em>, </td>\n        </tr>\n        <tr>\n          <td class=\"paramkey\"></td>\n          <td></td>\n          <td class=\"paramtype\">int&nbsp;</td>\n          <td class=\"paramname\"> <em>num_tracks</em></td><td>&nbsp;</td>\n        </tr>\n        <tr>\n          <td></td>\n          <td>)</td>\n          <td></td><td></td><td></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Get the number of new tracks in a playlist since the corresponding function <a class=\"el\" href=\"group__playlist.html#gadaad604c35e543363e1dd5b23c462db0\">sp_playlistcontainer_clear_unseen_tracks()</a> was called. The function always returns the number of new tracks, and fills the <code>tracks</code> array with the new tracks, but not more than specified in <code>num_tracks</code>. The function will return a negative value on failure.</p>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>pc</em>&nbsp;</td><td>Playlist container. </td></tr>\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>playlist</em>&nbsp;</td><td>Playlist object. </td></tr>\n    <tr><td valign=\"top\"><tt>[out]</tt>&nbsp;</td><td valign=\"top\"><em>tracks</em>&nbsp;</td><td>Array of pointer to new tracks (maybe NULL) </td></tr>\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>num_tracks</em>&nbsp;</td><td>Size of tracks array </td></tr>\n  </table>\n  </dd>\n</dl>\n<dl class=\"return\"><dt><b>Returns:</b></dt><dd>Returns the number of unseen tracks </dd></dl>\n\n</div>\n</div>\n<a class=\"anchor\" id=\"gae23cb67b4b26bca663034997c4418fa8\"></a><!-- doxytag: member=\"api.h::sp_playlistcontainer_is_loaded\" ref=\"gae23cb67b4b26bca663034997c4418fa8\" args=\"(sp_playlistcontainer *pc)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\">bool sp_playlistcontainer_is_loaded </td>\n          <td>(</td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__types.html#ga45a2febbe167483e48dab8d606d462d7\">sp_playlistcontainer</a> *&nbsp;</td>\n          <td class=\"paramname\"> <em>pc</em></td>\n          <td>&nbsp;)&nbsp;</td>\n          <td></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Return true if the playlistcontainer is fully loaded</p>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>pc</em>&nbsp;</td><td>Playlist container</td></tr>\n  </table>\n  </dd>\n</dl>\n<dl class=\"return\"><dt><b>Returns:</b></dt><dd>True if container is loaded</dd></dl>\n<dl class=\"note\"><dt><b>Note:</b></dt><dd>The container_loaded callback will be invoked when this flips to true </dd></dl>\n\n</div>\n</div>\n<a class=\"anchor\" id=\"gad9be708159957d4c1e5ef905550808c5\"></a><!-- doxytag: member=\"api.h::sp_playlistcontainer_move_playlist\" ref=\"gad9be708159957d4c1e5ef905550808c5\" args=\"(sp_playlistcontainer *pc, int index, int new_position, bool dry_run)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\"><a class=\"el\" href=\"group__error.html#gafd27986ce4cd9eeaeca8adda83c9eb6b\">sp_error</a> sp_playlistcontainer_move_playlist </td>\n          <td>(</td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__types.html#ga45a2febbe167483e48dab8d606d462d7\">sp_playlistcontainer</a> *&nbsp;</td>\n          <td class=\"paramname\"> <em>pc</em>, </td>\n        </tr>\n        <tr>\n          <td class=\"paramkey\"></td>\n          <td></td>\n          <td class=\"paramtype\">int&nbsp;</td>\n          <td class=\"paramname\"> <em>index</em>, </td>\n        </tr>\n        <tr>\n          <td class=\"paramkey\"></td>\n          <td></td>\n          <td class=\"paramtype\">int&nbsp;</td>\n          <td class=\"paramname\"> <em>new_position</em>, </td>\n        </tr>\n        <tr>\n          <td class=\"paramkey\"></td>\n          <td></td>\n          <td class=\"paramtype\">bool&nbsp;</td>\n          <td class=\"paramname\"> <em>dry_run</em></td><td>&nbsp;</td>\n        </tr>\n        <tr>\n          <td></td>\n          <td>)</td>\n          <td></td><td></td><td></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Move a playlist in the playlist container</p>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>pc</em>&nbsp;</td><td>Playlist container </td></tr>\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>index</em>&nbsp;</td><td>Index of playlist to be moved </td></tr>\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>new_position</em>&nbsp;</td><td>New position for the playlist </td></tr>\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>dry_run</em>&nbsp;</td><td>Do not execute the move, only check if it possible</td></tr>\n  </table>\n  </dd>\n</dl>\n<dl class=\"return\"><dt><b>Returns:</b></dt><dd>error One of the following errors, from <a class=\"el\" href=\"group__error.html#ga83154178d3a32668658734d2facfa22b\">sp_error</a> SP_ERROR_OK SP_ERROR_INDEX_OUT_OF_RANGE SP_ERROR_INVALID_INDATA - If trying to move a folder into itself </dd></dl>\n\n</div>\n</div>\n<a class=\"anchor\" id=\"ga7a1cbf558b2b364b8249d4ce432df700\"></a><!-- doxytag: member=\"api.h::sp_playlistcontainer_num_playlists\" ref=\"ga7a1cbf558b2b364b8249d4ce432df700\" args=\"(sp_playlistcontainer *pc)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\">int sp_playlistcontainer_num_playlists </td>\n          <td>(</td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__types.html#ga45a2febbe167483e48dab8d606d462d7\">sp_playlistcontainer</a> *&nbsp;</td>\n          <td class=\"paramname\"> <em>pc</em></td>\n          <td>&nbsp;)&nbsp;</td>\n          <td></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Return the number of playlists in the given playlist container</p>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>pc</em>&nbsp;</td><td>Playlist container</td></tr>\n  </table>\n  </dd>\n</dl>\n<dl class=\"return\"><dt><b>Returns:</b></dt><dd>Number of playlists, -1 if undefined</dd></dl>\n<dl class=\"see\"><dt><b>See also:</b></dt><dd><a class=\"el\" href=\"group__session.html#ga319767f0b795f1c46a08390b587c5671\">sp_session_playlistcontainer()</a> </dd></dl>\n<dl><dt><b>Examples: </b></dt><dd><a class=\"el\" href=\"jukebox_8c-example.html#a12\">jukebox.c</a>.</dd>\n</dl>\n</div>\n</div>\n<a class=\"anchor\" id=\"gad4fc67d1386dd637f778f4e735a36894\"></a><!-- doxytag: member=\"api.h::sp_playlistcontainer_owner\" ref=\"gad4fc67d1386dd637f778f4e735a36894\" args=\"(sp_playlistcontainer *pc)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\"><a class=\"el\" href=\"group__types.html#gaed2dbaa1eebd6752f76613daad9158bc\">sp_user</a>* sp_playlistcontainer_owner </td>\n          <td>(</td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__types.html#ga45a2febbe167483e48dab8d606d462d7\">sp_playlistcontainer</a> *&nbsp;</td>\n          <td class=\"paramname\"> <em>pc</em></td>\n          <td>&nbsp;)&nbsp;</td>\n          <td></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Return a pointer to the user object of the owner.</p>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>pc</em>&nbsp;</td><td>Playlist container. </td></tr>\n  </table>\n  </dd>\n</dl>\n<dl class=\"return\"><dt><b>Returns:</b></dt><dd>The user object or NULL if unknown or none. </dd></dl>\n\n</div>\n</div>\n<a class=\"anchor\" id=\"ga5ddd8c8064c281a14c6fd7877f522dc6\"></a><!-- doxytag: member=\"api.h::sp_playlistcontainer_playlist\" ref=\"ga5ddd8c8064c281a14c6fd7877f522dc6\" args=\"(sp_playlistcontainer *pc, int index)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\"><a class=\"el\" href=\"group__types.html#ga1bcf54cbc117a20ab2c15e59eb3a8174\">sp_playlist</a>* sp_playlistcontainer_playlist </td>\n          <td>(</td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__types.html#ga45a2febbe167483e48dab8d606d462d7\">sp_playlistcontainer</a> *&nbsp;</td>\n          <td class=\"paramname\"> <em>pc</em>, </td>\n        </tr>\n        <tr>\n          <td class=\"paramkey\"></td>\n          <td></td>\n          <td class=\"paramtype\">int&nbsp;</td>\n          <td class=\"paramname\"> <em>index</em></td><td>&nbsp;</td>\n        </tr>\n        <tr>\n          <td></td>\n          <td>)</td>\n          <td></td><td></td><td></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Return a pointer to the playlist at a specific index</p>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>pc</em>&nbsp;</td><td>Playlist container </td></tr>\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>index</em>&nbsp;</td><td>Index in playlist container. Should be in the interval [0, <a class=\"el\" href=\"group__playlist.html#ga7a1cbf558b2b364b8249d4ce432df700\">sp_playlistcontainer_num_playlists()</a> - 1]</td></tr>\n  </table>\n  </dd>\n</dl>\n<dl class=\"return\"><dt><b>Returns:</b></dt><dd>The playlist object</dd></dl>\n<dl class=\"see\"><dt><b>See also:</b></dt><dd><a class=\"el\" href=\"group__session.html#ga319767f0b795f1c46a08390b587c5671\">sp_session_playlistcontainer()</a> </dd></dl>\n<dl><dt><b>Examples: </b></dt><dd><a class=\"el\" href=\"jukebox_8c-example.html#a17\">jukebox.c</a>.</dd>\n</dl>\n</div>\n</div>\n<a class=\"anchor\" id=\"ga6939f9db71199612fc5a19d395e3a7f8\"></a><!-- doxytag: member=\"api.h::sp_playlistcontainer_playlist_folder_id\" ref=\"ga6939f9db71199612fc5a19d395e3a7f8\" args=\"(sp_playlistcontainer *pc, int index)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\">sp_uint64 sp_playlistcontainer_playlist_folder_id </td>\n          <td>(</td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__types.html#ga45a2febbe167483e48dab8d606d462d7\">sp_playlistcontainer</a> *&nbsp;</td>\n          <td class=\"paramname\"> <em>pc</em>, </td>\n        </tr>\n        <tr>\n          <td class=\"paramkey\"></td>\n          <td></td>\n          <td class=\"paramtype\">int&nbsp;</td>\n          <td class=\"paramname\"> <em>index</em></td><td>&nbsp;</td>\n        </tr>\n        <tr>\n          <td></td>\n          <td>)</td>\n          <td></td><td></td><td></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Return the folder id at <em>index</em> </p>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>pc</em>&nbsp;</td><td>Playlist container </td></tr>\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>index</em>&nbsp;</td><td>Index in playlist container. Should be in the interval [0, <a class=\"el\" href=\"group__playlist.html#ga7a1cbf558b2b364b8249d4ce432df700\">sp_playlistcontainer_num_playlists()</a> - 1]</td></tr>\n  </table>\n  </dd>\n</dl>\n<dl class=\"return\"><dt><b>Returns:</b></dt><dd>The group ID of the folder. Returns 0 on index out of range, pc being NULL or indexed item not being a folder</dd></dl>\n<dl class=\"see\"><dt><b>See also:</b></dt><dd><a class=\"el\" href=\"group__session.html#ga319767f0b795f1c46a08390b587c5671\">sp_session_playlistcontainer()</a> </dd></dl>\n\n</div>\n</div>\n<a class=\"anchor\" id=\"ga852e5f5bcd4520be2e3d6d5d94def44a\"></a><!-- doxytag: member=\"api.h::sp_playlistcontainer_playlist_folder_name\" ref=\"ga852e5f5bcd4520be2e3d6d5d94def44a\" args=\"(sp_playlistcontainer *pc, int index, char *buffer, int buffer_size)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\"><a class=\"el\" href=\"group__error.html#gafd27986ce4cd9eeaeca8adda83c9eb6b\">sp_error</a> sp_playlistcontainer_playlist_folder_name </td>\n          <td>(</td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__types.html#ga45a2febbe167483e48dab8d606d462d7\">sp_playlistcontainer</a> *&nbsp;</td>\n          <td class=\"paramname\"> <em>pc</em>, </td>\n        </tr>\n        <tr>\n          <td class=\"paramkey\"></td>\n          <td></td>\n          <td class=\"paramtype\">int&nbsp;</td>\n          <td class=\"paramname\"> <em>index</em>, </td>\n        </tr>\n        <tr>\n          <td class=\"paramkey\"></td>\n          <td></td>\n          <td class=\"paramtype\">char *&nbsp;</td>\n          <td class=\"paramname\"> <em>buffer</em>, </td>\n        </tr>\n        <tr>\n          <td class=\"paramkey\"></td>\n          <td></td>\n          <td class=\"paramtype\">int&nbsp;</td>\n          <td class=\"paramname\"> <em>buffer_size</em></td><td>&nbsp;</td>\n        </tr>\n        <tr>\n          <td></td>\n          <td>)</td>\n          <td></td><td></td><td></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Return the folder name at <em>index</em> </p>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>pc</em>&nbsp;</td><td>Playlist container </td></tr>\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>index</em>&nbsp;</td><td>Index in playlist container. Should be in the interval [0, <a class=\"el\" href=\"group__playlist.html#ga7a1cbf558b2b364b8249d4ce432df700\">sp_playlistcontainer_num_playlists()</a> - 1]. Index should point at a start-folder entry, otherwise the empty string is written to buffer. </td></tr>\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>buffer</em>&nbsp;</td><td>Pointer to char[] where to store folder name </td></tr>\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>buffer_size</em>&nbsp;</td><td>Size of array</td></tr>\n  </table>\n  </dd>\n</dl>\n<dl class=\"return\"><dt><b>Returns:</b></dt><dd>One of the following errors, from <a class=\"el\" href=\"group__error.html#ga83154178d3a32668658734d2facfa22b\">sp_error</a> SP_ERROR_OK SP_ERROR_INDEX_OUT_OF_RANGE</dd></dl>\n<dl class=\"see\"><dt><b>See also:</b></dt><dd><a class=\"el\" href=\"group__session.html#ga319767f0b795f1c46a08390b587c5671\">sp_session_playlistcontainer()</a> </dd></dl>\n\n</div>\n</div>\n<a class=\"anchor\" id=\"ga79286860a3eeada495e97c5ad1fd7ebf\"></a><!-- doxytag: member=\"api.h::sp_playlistcontainer_playlist_type\" ref=\"ga79286860a3eeada495e97c5ad1fd7ebf\" args=\"(sp_playlistcontainer *pc, int index)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\"><a class=\"el\" href=\"group__session.html#gafdd7117213605e6f2671c4f289b44609\">sp_playlist_type</a> sp_playlistcontainer_playlist_type </td>\n          <td>(</td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__types.html#ga45a2febbe167483e48dab8d606d462d7\">sp_playlistcontainer</a> *&nbsp;</td>\n          <td class=\"paramname\"> <em>pc</em>, </td>\n        </tr>\n        <tr>\n          <td class=\"paramkey\"></td>\n          <td></td>\n          <td class=\"paramtype\">int&nbsp;</td>\n          <td class=\"paramname\"> <em>index</em></td><td>&nbsp;</td>\n        </tr>\n        <tr>\n          <td></td>\n          <td>)</td>\n          <td></td><td></td><td></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Return the type of the playlist at a <em>index</em> </p>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>pc</em>&nbsp;</td><td>Playlist container </td></tr>\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>index</em>&nbsp;</td><td>Index in playlist container. Should be in the interval [0, <a class=\"el\" href=\"group__playlist.html#ga7a1cbf558b2b364b8249d4ce432df700\">sp_playlistcontainer_num_playlists()</a> - 1]</td></tr>\n  </table>\n  </dd>\n</dl>\n<dl class=\"return\"><dt><b>Returns:</b></dt><dd>Type of the playlist, </dd></dl>\n<dl class=\"see\"><dt><b>See also:</b></dt><dd><a class=\"el\" href=\"group__session.html#ga86723f553db2db6a8f507cd748948ad4\">sp_playlist_type</a></dd>\n<dd>\n<a class=\"el\" href=\"group__session.html#ga319767f0b795f1c46a08390b587c5671\">sp_session_playlistcontainer()</a> </dd></dl>\n\n</div>\n</div>\n<a class=\"anchor\" id=\"ga0311c7c3c4f26028e5edd4aacb36dbf8\"></a><!-- doxytag: member=\"api.h::sp_playlistcontainer_release\" ref=\"ga0311c7c3c4f26028e5edd4aacb36dbf8\" args=\"(sp_playlistcontainer *pc)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\"><a class=\"el\" href=\"group__error.html#gafd27986ce4cd9eeaeca8adda83c9eb6b\">sp_error</a> sp_playlistcontainer_release </td>\n          <td>(</td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__types.html#ga45a2febbe167483e48dab8d606d462d7\">sp_playlistcontainer</a> *&nbsp;</td>\n          <td class=\"paramname\"> <em>pc</em></td>\n          <td>&nbsp;)&nbsp;</td>\n          <td></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Release reference count on playlistconatiner object</p>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>pc</em>&nbsp;</td><td>Playlist container. </td></tr>\n  </table>\n  </dd>\n</dl>\n<dl class=\"return\"><dt><b>Returns:</b></dt><dd>One of the following errors, from <a class=\"el\" href=\"group__error.html#ga83154178d3a32668658734d2facfa22b\">sp_error</a> SP_ERROR_OK </dd></dl>\n\n</div>\n</div>\n<a class=\"anchor\" id=\"gafb5242b8f0f9964cec29d32f4d6c1164\"></a><!-- doxytag: member=\"api.h::sp_playlistcontainer_remove_callbacks\" ref=\"gafb5242b8f0f9964cec29d32f4d6c1164\" args=\"(sp_playlistcontainer *pc, sp_playlistcontainer_callbacks *callbacks, void *userdata)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\"><a class=\"el\" href=\"group__error.html#gafd27986ce4cd9eeaeca8adda83c9eb6b\">sp_error</a> sp_playlistcontainer_remove_callbacks </td>\n          <td>(</td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__types.html#ga45a2febbe167483e48dab8d606d462d7\">sp_playlistcontainer</a> *&nbsp;</td>\n          <td class=\"paramname\"> <em>pc</em>, </td>\n        </tr>\n        <tr>\n          <td class=\"paramkey\"></td>\n          <td></td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"structsp__playlistcontainer__callbacks.html\">sp_playlistcontainer_callbacks</a> *&nbsp;</td>\n          <td class=\"paramname\"> <em>callbacks</em>, </td>\n        </tr>\n        <tr>\n          <td class=\"paramkey\"></td>\n          <td></td>\n          <td class=\"paramtype\">void *&nbsp;</td>\n          <td class=\"paramname\"> <em>userdata</em></td><td>&nbsp;</td>\n        </tr>\n        <tr>\n          <td></td>\n          <td>)</td>\n          <td></td><td></td><td></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Unregister interest in changes to a playlist container</p>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>pc</em>&nbsp;</td><td>Playlist container </td></tr>\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>callbacks</em>&nbsp;</td><td>Callbacks, see <a class=\"el\" href=\"structsp__playlistcontainer__callbacks.html\">sp_playlistcontainer_callbacks</a> </td></tr>\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>userdata</em>&nbsp;</td><td>Opaque value passed to callbacks.</td></tr>\n  </table>\n  </dd>\n</dl>\n<dl class=\"see\"><dt><b>See also:</b></dt><dd><a class=\"el\" href=\"group__session.html#ga319767f0b795f1c46a08390b587c5671\">sp_session_playlistcontainer()</a> </dd>\n<dd>\n<a class=\"el\" href=\"group__playlist.html#ga1976cb49c391cdd2dbe7c40d1bc71570\">sp_playlistcontainer_add_callbacks</a> </dd></dl>\n<dl class=\"return\"><dt><b>Returns:</b></dt><dd>One of the following errors, from <a class=\"el\" href=\"group__error.html#ga83154178d3a32668658734d2facfa22b\">sp_error</a> SP_ERROR_OK </dd></dl>\n\n</div>\n</div>\n<a class=\"anchor\" id=\"ga1ae1d51c4305940ae5c5c98c12be0afc\"></a><!-- doxytag: member=\"api.h::sp_playlistcontainer_remove_playlist\" ref=\"ga1ae1d51c4305940ae5c5c98c12be0afc\" args=\"(sp_playlistcontainer *pc, int index)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\"><a class=\"el\" href=\"group__error.html#gafd27986ce4cd9eeaeca8adda83c9eb6b\">sp_error</a> sp_playlistcontainer_remove_playlist </td>\n          <td>(</td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__types.html#ga45a2febbe167483e48dab8d606d462d7\">sp_playlistcontainer</a> *&nbsp;</td>\n          <td class=\"paramname\"> <em>pc</em>, </td>\n        </tr>\n        <tr>\n          <td class=\"paramkey\"></td>\n          <td></td>\n          <td class=\"paramtype\">int&nbsp;</td>\n          <td class=\"paramname\"> <em>index</em></td><td>&nbsp;</td>\n        </tr>\n        <tr>\n          <td></td>\n          <td>)</td>\n          <td></td><td></td><td></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Remove playlist at index from the given playlist container</p>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>pc</em>&nbsp;</td><td>Playlist container </td></tr>\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>index</em>&nbsp;</td><td>Index of playlist to be removed</td></tr>\n  </table>\n  </dd>\n</dl>\n<dl class=\"return\"><dt><b>Returns:</b></dt><dd>error One of the following errors, from <a class=\"el\" href=\"group__error.html#ga83154178d3a32668658734d2facfa22b\">sp_error</a> SP_ERROR_OK SP_ERROR_INDEX_OUT_OF_RANGE </dd></dl>\n\n</div>\n</div>\n</div>\n<hr size=\"1\"><address style=\"text-align: right;\"><small>\nGenerated on Wed Jun 13 2012 14:22:40.<br>\nCopyright &copy; 2006&ndash;2012 Spotify Ltd</small></address>\n</body>\n</html>\n"
  },
  {
    "path": "libspotify/docs/html/group__search.html",
    "content": "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\n<html xmlns=\"http://www.w3.org/1999/xhtml\">\n<head>\n<meta http-equiv=\"Content-Type\" content=\"text/xhtml;charset=UTF-8\"/>\n<title>libspotify: Search subsystem</title>\n<link href=\"tabs.css\" rel=\"stylesheet\" type=\"text/css\"/>\n<link href=\"doxygen.css\" rel=\"stylesheet\" type=\"text/css\"/>\n</head>\n<body>\n<!-- Generated by Doxygen 1.7.1 -->\n<div class=\"navigation\" id=\"top\">\n  <div class=\"tabs\">\n    <ul class=\"tablist\">\n      <li><a href=\"index.html\"><span>Main&nbsp;Page</span></a></li>\n      <li><a href=\"modules.html\"><span>Modules</span></a></li>\n      <li><a href=\"annotated.html\"><span>Data&nbsp;Structures</span></a></li>\n      <li><a href=\"files.html\"><span>Files</span></a></li>\n      <li><a href=\"examples.html\"><span>Examples</span></a></li>\n    </ul>\n  </div>\n</div>\n<div class=\"header\">\n  <div class=\"summary\">\n<a href=\"#typedef-members\">Typedefs</a> &#124;\n<a href=\"#func-members\">Functions</a>  </div>\n  <div class=\"headertitle\">\n<h1>Search subsystem</h1>  </div>\n</div>\n<div class=\"contents\">\n<table class=\"memberdecls\">\n<tr><td colspan=\"2\"><h2><a name=\"typedef-members\"></a>\nTypedefs</h2></td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">typedef void&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__search.html#gabcd51c99a318b9f36dfe2948d8209bb1\">search_complete_cb</a> (<a class=\"el\" href=\"group__types.html#gac95893a6b23d4b19f6f149eed6ead1fd\">sp_search</a> *result, void *userdata)</td></tr>\n<tr><td colspan=\"2\"><h2><a name=\"func-members\"></a>\nFunctions</h2></td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__types.html#gac95893a6b23d4b19f6f149eed6ead1fd\">sp_search</a> *&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__search.html#ga2f64dfbcc1313e7d5179998cb28208d4\">sp_search_create</a> (<a class=\"el\" href=\"group__types.html#ga70dd19c6f824cf6a159575aa4c128b53\">sp_session</a> *session, const char *query, int track_offset, int track_count, int album_offset, int album_count, int artist_offset, int artist_count, int playlist_offset, int playlist_count, <a class=\"el\" href=\"group__session.html#ga99e8e9176ce40fff08a9be8b944edb09\">sp_search_type</a> search_type, <a class=\"el\" href=\"group__search.html#gabcd51c99a318b9f36dfe2948d8209bb1\">search_complete_cb</a> *callback, void *userdata)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">bool&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__search.html#ga70e8c404d8c7ce0bbef70c2b274417cd\">sp_search_is_loaded</a> (<a class=\"el\" href=\"group__types.html#gac95893a6b23d4b19f6f149eed6ead1fd\">sp_search</a> *search)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__error.html#gafd27986ce4cd9eeaeca8adda83c9eb6b\">sp_error</a>&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__search.html#ga7cf655e37a823f952d30270d4fb60f10\">sp_search_error</a> (<a class=\"el\" href=\"group__types.html#gac95893a6b23d4b19f6f149eed6ead1fd\">sp_search</a> *search)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">int&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__search.html#ga1dd18cf7b3b3b7f4bf6e92a2140378d0\">sp_search_num_tracks</a> (<a class=\"el\" href=\"group__types.html#gac95893a6b23d4b19f6f149eed6ead1fd\">sp_search</a> *search)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__types.html#ga47bbd2262f0c8b5d7147af7d62198e48\">sp_track</a> *&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__search.html#gae9da7ca59ce0bbd73f7bcef4e15c4da8\">sp_search_track</a> (<a class=\"el\" href=\"group__types.html#gac95893a6b23d4b19f6f149eed6ead1fd\">sp_search</a> *search, int index)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">int&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__search.html#ga0c456a6396c4c05fbc8677ea641ef1f7\">sp_search_num_albums</a> (<a class=\"el\" href=\"group__types.html#gac95893a6b23d4b19f6f149eed6ead1fd\">sp_search</a> *search)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__types.html#ga6fd3e5de729c429fef3ff18ece6dcfad\">sp_album</a> *&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__search.html#ga4ba7723e70db0c6a4569c4bcd44f0e98\">sp_search_album</a> (<a class=\"el\" href=\"group__types.html#gac95893a6b23d4b19f6f149eed6ead1fd\">sp_search</a> *search, int index)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">int&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__search.html#gaa9f007f439d8241bf632f9abb8d926c9\">sp_search_num_playlists</a> (<a class=\"el\" href=\"group__types.html#gac95893a6b23d4b19f6f149eed6ead1fd\">sp_search</a> *search)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__types.html#ga1bcf54cbc117a20ab2c15e59eb3a8174\">sp_playlist</a> *&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__search.html#ga4175fba17f355b1c0bd361357181ea35\">sp_search_playlist</a> (<a class=\"el\" href=\"group__types.html#gac95893a6b23d4b19f6f149eed6ead1fd\">sp_search</a> *search, int index)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">const char *&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__search.html#ga933cd5d5a0ccca9906082ca4549a4ed7\">sp_search_playlist_name</a> (<a class=\"el\" href=\"group__types.html#gac95893a6b23d4b19f6f149eed6ead1fd\">sp_search</a> *search, int index)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">const char *&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__search.html#ga0071a3d30f0f0c4e477bf923e9014ff5\">sp_search_playlist_uri</a> (<a class=\"el\" href=\"group__types.html#gac95893a6b23d4b19f6f149eed6ead1fd\">sp_search</a> *search, int index)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">const char *&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__search.html#gac4463fab4ea25e0a5d5079c959a1781c\">sp_search_playlist_image_uri</a> (<a class=\"el\" href=\"group__types.html#gac95893a6b23d4b19f6f149eed6ead1fd\">sp_search</a> *search, int index)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">int&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__search.html#gabd375a613c2dadecad8c13f8aca6f2d3\">sp_search_num_artists</a> (<a class=\"el\" href=\"group__types.html#gac95893a6b23d4b19f6f149eed6ead1fd\">sp_search</a> *search)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__types.html#ga31764fbd69618c10be173c6c03d4c1bc\">sp_artist</a> *&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__search.html#ga79b3d532d5a20a3b2bf2a087eead7888\">sp_search_artist</a> (<a class=\"el\" href=\"group__types.html#gac95893a6b23d4b19f6f149eed6ead1fd\">sp_search</a> *search, int index)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">const char *&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__search.html#ga127e9c2bf98e3602ecfc2926b9d242bf\">sp_search_query</a> (<a class=\"el\" href=\"group__types.html#gac95893a6b23d4b19f6f149eed6ead1fd\">sp_search</a> *search)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">const char *&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__search.html#ga8561c1da8b93ecdc8f2d325a9d19199b\">sp_search_did_you_mean</a> (<a class=\"el\" href=\"group__types.html#gac95893a6b23d4b19f6f149eed6ead1fd\">sp_search</a> *search)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">int&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__search.html#gab4e50582c517b4639fd1afd6fb011587\">sp_search_total_tracks</a> (<a class=\"el\" href=\"group__types.html#gac95893a6b23d4b19f6f149eed6ead1fd\">sp_search</a> *search)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">int&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__search.html#gaafd3b228adbc028937383d0d45730581\">sp_search_total_albums</a> (<a class=\"el\" href=\"group__types.html#gac95893a6b23d4b19f6f149eed6ead1fd\">sp_search</a> *search)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">int&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__search.html#ga305a4118625e0f70cfb14161a0112fd5\">sp_search_total_artists</a> (<a class=\"el\" href=\"group__types.html#gac95893a6b23d4b19f6f149eed6ead1fd\">sp_search</a> *search)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">int&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__search.html#ga2e286415a6ba8dbf85ea677906f2798c\">sp_search_total_playlists</a> (<a class=\"el\" href=\"group__types.html#gac95893a6b23d4b19f6f149eed6ead1fd\">sp_search</a> *search)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__error.html#gafd27986ce4cd9eeaeca8adda83c9eb6b\">sp_error</a>&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__search.html#ga92e45a5edb1e33e64fdb857bd8eb9ad5\">sp_search_add_ref</a> (<a class=\"el\" href=\"group__types.html#gac95893a6b23d4b19f6f149eed6ead1fd\">sp_search</a> *search)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__error.html#gafd27986ce4cd9eeaeca8adda83c9eb6b\">sp_error</a>&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__search.html#ga4e01d43067d9f8c533c985f90143821b\">sp_search_release</a> (<a class=\"el\" href=\"group__types.html#gac95893a6b23d4b19f6f149eed6ead1fd\">sp_search</a> *search)</td></tr>\n</table>\n<hr/><h2>Typedef Documentation</h2>\n<a class=\"anchor\" id=\"gabcd51c99a318b9f36dfe2948d8209bb1\"></a><!-- doxytag: member=\"api.h::search_complete_cb\" ref=\"gabcd51c99a318b9f36dfe2948d8209bb1\" args=\"(sp_search *result, void *userdata)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\">typedef void <a class=\"el\" href=\"group__search.html#gabcd51c99a318b9f36dfe2948d8209bb1\">search_complete_cb</a>(<a class=\"el\" href=\"group__types.html#gac95893a6b23d4b19f6f149eed6ead1fd\">sp_search</a> *result, void *userdata)</td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>The type of a callback used in <a class=\"el\" href=\"group__search.html#ga2f64dfbcc1313e7d5179998cb28208d4\">sp_search_create()</a></p>\n<p>When this callback is called, the <a class=\"el\" href=\"group__track.html#ga8b69cf193679c7e00031ae43e61c6a54\">sp_track_is_loaded()</a>, <a class=\"el\" href=\"group__album.html#ga46fbfa98be12c2f4067d5e679552cfb9\">sp_album_is_loaded()</a>, and <a class=\"el\" href=\"group__artist.html#gafc98f5093184a7ac7ce608302b0971ea\">sp_artist_is_loaded()</a> functions will return non-zero for the objects contained in the search result.</p>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>result</em>&nbsp;</td><td>The same pointer returned by <a class=\"el\" href=\"group__search.html#ga2f64dfbcc1313e7d5179998cb28208d4\">sp_search_create()</a> </td></tr>\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>userdata</em>&nbsp;</td><td>The opaque pointer given to <a class=\"el\" href=\"group__search.html#ga2f64dfbcc1313e7d5179998cb28208d4\">sp_search_create()</a> </td></tr>\n  </table>\n  </dd>\n</dl>\n\n</div>\n</div>\n<hr/><h2>Function Documentation</h2>\n<a class=\"anchor\" id=\"ga92e45a5edb1e33e64fdb857bd8eb9ad5\"></a><!-- doxytag: member=\"api.h::sp_search_add_ref\" ref=\"ga92e45a5edb1e33e64fdb857bd8eb9ad5\" args=\"(sp_search *search)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\"><a class=\"el\" href=\"group__error.html#gafd27986ce4cd9eeaeca8adda83c9eb6b\">sp_error</a> sp_search_add_ref </td>\n          <td>(</td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__types.html#gac95893a6b23d4b19f6f149eed6ead1fd\">sp_search</a> *&nbsp;</td>\n          <td class=\"paramname\"> <em>search</em></td>\n          <td>&nbsp;)&nbsp;</td>\n          <td></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Increase the reference count of a search result</p>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>search</em>&nbsp;</td><td>The search result object </td></tr>\n  </table>\n  </dd>\n</dl>\n<dl class=\"return\"><dt><b>Returns:</b></dt><dd>One of the following errors, from <a class=\"el\" href=\"group__error.html#ga83154178d3a32668658734d2facfa22b\">sp_error</a> SP_ERROR_OK </dd></dl>\n\n</div>\n</div>\n<a class=\"anchor\" id=\"ga4ba7723e70db0c6a4569c4bcd44f0e98\"></a><!-- doxytag: member=\"api.h::sp_search_album\" ref=\"ga4ba7723e70db0c6a4569c4bcd44f0e98\" args=\"(sp_search *search, int index)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\"><a class=\"el\" href=\"group__types.html#ga6fd3e5de729c429fef3ff18ece6dcfad\">sp_album</a>* sp_search_album </td>\n          <td>(</td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__types.html#gac95893a6b23d4b19f6f149eed6ead1fd\">sp_search</a> *&nbsp;</td>\n          <td class=\"paramname\"> <em>search</em>, </td>\n        </tr>\n        <tr>\n          <td class=\"paramkey\"></td>\n          <td></td>\n          <td class=\"paramtype\">int&nbsp;</td>\n          <td class=\"paramname\"> <em>index</em></td><td>&nbsp;</td>\n        </tr>\n        <tr>\n          <td></td>\n          <td>)</td>\n          <td></td><td></td><td></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Return the album at the given index in the given search object</p>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>search</em>&nbsp;</td><td>Search object </td></tr>\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>index</em>&nbsp;</td><td>Index of the wanted album. Should be in the interval [0, <a class=\"el\" href=\"group__search.html#ga0c456a6396c4c05fbc8677ea641ef1f7\">sp_search_num_albums()</a> - 1]</td></tr>\n  </table>\n  </dd>\n</dl>\n<dl class=\"return\"><dt><b>Returns:</b></dt><dd>The album at the given index in the given search object </dd></dl>\n<dl><dt><b>Examples: </b></dt><dd><a class=\"el\" href=\"search_8c-example.html#a9\">search.c</a>.</dd>\n</dl>\n</div>\n</div>\n<a class=\"anchor\" id=\"ga79b3d532d5a20a3b2bf2a087eead7888\"></a><!-- doxytag: member=\"api.h::sp_search_artist\" ref=\"ga79b3d532d5a20a3b2bf2a087eead7888\" args=\"(sp_search *search, int index)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\"><a class=\"el\" href=\"group__types.html#ga31764fbd69618c10be173c6c03d4c1bc\">sp_artist</a>* sp_search_artist </td>\n          <td>(</td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__types.html#gac95893a6b23d4b19f6f149eed6ead1fd\">sp_search</a> *&nbsp;</td>\n          <td class=\"paramname\"> <em>search</em>, </td>\n        </tr>\n        <tr>\n          <td class=\"paramkey\"></td>\n          <td></td>\n          <td class=\"paramtype\">int&nbsp;</td>\n          <td class=\"paramname\"> <em>index</em></td><td>&nbsp;</td>\n        </tr>\n        <tr>\n          <td></td>\n          <td>)</td>\n          <td></td><td></td><td></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Return the artist at the given index in the given search object</p>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>search</em>&nbsp;</td><td>Search object </td></tr>\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>index</em>&nbsp;</td><td>Index of the wanted artist. Should be in the interval [0, <a class=\"el\" href=\"group__search.html#gabd375a613c2dadecad8c13f8aca6f2d3\">sp_search_num_artists()</a> - 1]</td></tr>\n  </table>\n  </dd>\n</dl>\n<dl class=\"return\"><dt><b>Returns:</b></dt><dd>The artist at the given index in the given search object </dd></dl>\n<dl><dt><b>Examples: </b></dt><dd><a class=\"el\" href=\"search_8c-example.html#a11\">search.c</a>.</dd>\n</dl>\n</div>\n</div>\n<a class=\"anchor\" id=\"ga2f64dfbcc1313e7d5179998cb28208d4\"></a><!-- doxytag: member=\"api.h::sp_search_create\" ref=\"ga2f64dfbcc1313e7d5179998cb28208d4\" args=\"(sp_session *session, const char *query, int track_offset, int track_count, int album_offset, int album_count, int artist_offset, int artist_count, int playlist_offset, int playlist_count, sp_search_type search_type, search_complete_cb *callback, void *userdata)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\"><a class=\"el\" href=\"group__types.html#gac95893a6b23d4b19f6f149eed6ead1fd\">sp_search</a>* sp_search_create </td>\n          <td>(</td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__types.html#ga70dd19c6f824cf6a159575aa4c128b53\">sp_session</a> *&nbsp;</td>\n          <td class=\"paramname\"> <em>session</em>, </td>\n        </tr>\n        <tr>\n          <td class=\"paramkey\"></td>\n          <td></td>\n          <td class=\"paramtype\">const char *&nbsp;</td>\n          <td class=\"paramname\"> <em>query</em>, </td>\n        </tr>\n        <tr>\n          <td class=\"paramkey\"></td>\n          <td></td>\n          <td class=\"paramtype\">int&nbsp;</td>\n          <td class=\"paramname\"> <em>track_offset</em>, </td>\n        </tr>\n        <tr>\n          <td class=\"paramkey\"></td>\n          <td></td>\n          <td class=\"paramtype\">int&nbsp;</td>\n          <td class=\"paramname\"> <em>track_count</em>, </td>\n        </tr>\n        <tr>\n          <td class=\"paramkey\"></td>\n          <td></td>\n          <td class=\"paramtype\">int&nbsp;</td>\n          <td class=\"paramname\"> <em>album_offset</em>, </td>\n        </tr>\n        <tr>\n          <td class=\"paramkey\"></td>\n          <td></td>\n          <td class=\"paramtype\">int&nbsp;</td>\n          <td class=\"paramname\"> <em>album_count</em>, </td>\n        </tr>\n        <tr>\n          <td class=\"paramkey\"></td>\n          <td></td>\n          <td class=\"paramtype\">int&nbsp;</td>\n          <td class=\"paramname\"> <em>artist_offset</em>, </td>\n        </tr>\n        <tr>\n          <td class=\"paramkey\"></td>\n          <td></td>\n          <td class=\"paramtype\">int&nbsp;</td>\n          <td class=\"paramname\"> <em>artist_count</em>, </td>\n        </tr>\n        <tr>\n          <td class=\"paramkey\"></td>\n          <td></td>\n          <td class=\"paramtype\">int&nbsp;</td>\n          <td class=\"paramname\"> <em>playlist_offset</em>, </td>\n        </tr>\n        <tr>\n          <td class=\"paramkey\"></td>\n          <td></td>\n          <td class=\"paramtype\">int&nbsp;</td>\n          <td class=\"paramname\"> <em>playlist_count</em>, </td>\n        </tr>\n        <tr>\n          <td class=\"paramkey\"></td>\n          <td></td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__session.html#ga99e8e9176ce40fff08a9be8b944edb09\">sp_search_type</a>&nbsp;</td>\n          <td class=\"paramname\"> <em>search_type</em>, </td>\n        </tr>\n        <tr>\n          <td class=\"paramkey\"></td>\n          <td></td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__search.html#gabcd51c99a318b9f36dfe2948d8209bb1\">search_complete_cb</a> *&nbsp;</td>\n          <td class=\"paramname\"> <em>callback</em>, </td>\n        </tr>\n        <tr>\n          <td class=\"paramkey\"></td>\n          <td></td>\n          <td class=\"paramtype\">void *&nbsp;</td>\n          <td class=\"paramname\"> <em>userdata</em></td><td>&nbsp;</td>\n        </tr>\n        <tr>\n          <td></td>\n          <td>)</td>\n          <td></td><td></td><td></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Create a search object from the given query</p>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>session</em>&nbsp;</td><td>Session </td></tr>\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>query</em>&nbsp;</td><td>Query search string, e.g. 'The Rolling Stones' or 'album:\"The Black Album\"' </td></tr>\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>track_offset</em>&nbsp;</td><td>The offset among the tracks of the result </td></tr>\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>track_count</em>&nbsp;</td><td>The number of tracks to ask for </td></tr>\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>album_offset</em>&nbsp;</td><td>The offset among the albums of the result </td></tr>\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>album_count</em>&nbsp;</td><td>The number of albums to ask for </td></tr>\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>artist_offset</em>&nbsp;</td><td>The offset among the artists of the result </td></tr>\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>artist_count</em>&nbsp;</td><td>The number of artists to ask for </td></tr>\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>playlist_offset</em>&nbsp;</td><td>The offset among the playlists of the result </td></tr>\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>playlist_count</em>&nbsp;</td><td>The number of playlists to ask for </td></tr>\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>search_type</em>&nbsp;</td><td>Type of search, can be used for suggest searches </td></tr>\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>callback</em>&nbsp;</td><td>Callback that will be called once the search operation is complete. Pass NULL if you are not interested in this event. </td></tr>\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>userdata</em>&nbsp;</td><td>Opaque pointer passed to <code>callback</code> </td></tr>\n  </table>\n  </dd>\n</dl>\n<dl class=\"return\"><dt><b>Returns:</b></dt><dd>Pointer to a search object. To free the object, use <a class=\"el\" href=\"group__search.html#ga4e01d43067d9f8c533c985f90143821b\">sp_search_release()</a> </dd></dl>\n<dl><dt><b>Examples: </b></dt><dd><a class=\"el\" href=\"search_8c-example.html#a18\">search.c</a>.</dd>\n</dl>\n</div>\n</div>\n<a class=\"anchor\" id=\"ga8561c1da8b93ecdc8f2d325a9d19199b\"></a><!-- doxytag: member=\"api.h::sp_search_did_you_mean\" ref=\"ga8561c1da8b93ecdc8f2d325a9d19199b\" args=\"(sp_search *search)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\">const char* sp_search_did_you_mean </td>\n          <td>(</td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__types.html#gac95893a6b23d4b19f6f149eed6ead1fd\">sp_search</a> *&nbsp;</td>\n          <td class=\"paramname\"> <em>search</em></td>\n          <td>&nbsp;)&nbsp;</td>\n          <td></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Return the \"Did you mean\" query for the given search object</p>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>search</em>&nbsp;</td><td>Search object</td></tr>\n  </table>\n  </dd>\n</dl>\n<dl class=\"return\"><dt><b>Returns:</b></dt><dd>The \"Did you mean\" query for the given search object, or the empty string if no such info is available </dd></dl>\n<dl><dt><b>Examples: </b></dt><dd><a class=\"el\" href=\"search_8c-example.html#a4\">search.c</a>.</dd>\n</dl>\n</div>\n</div>\n<a class=\"anchor\" id=\"ga7cf655e37a823f952d30270d4fb60f10\"></a><!-- doxytag: member=\"api.h::sp_search_error\" ref=\"ga7cf655e37a823f952d30270d4fb60f10\" args=\"(sp_search *search)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\"><a class=\"el\" href=\"group__error.html#gafd27986ce4cd9eeaeca8adda83c9eb6b\">sp_error</a> sp_search_error </td>\n          <td>(</td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__types.html#gac95893a6b23d4b19f6f149eed6ead1fd\">sp_search</a> *&nbsp;</td>\n          <td class=\"paramname\"> <em>search</em></td>\n          <td>&nbsp;)&nbsp;</td>\n          <td></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Check if search returned an error code.</p>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>search</em>&nbsp;</td><td>Search object</td></tr>\n  </table>\n  </dd>\n</dl>\n<dl class=\"return\"><dt><b>Returns:</b></dt><dd>One of the following errors, from <a class=\"el\" href=\"group__error.html#ga83154178d3a32668658734d2facfa22b\">sp_error</a> SP_ERROR_OK SP_ERROR_IS_LOADING SP_ERROR_OTHER_PERMANENT SP_ERROR_OTHER_TRANSIENT </dd></dl>\n<dl><dt><b>Examples: </b></dt><dd><a class=\"el\" href=\"search_8c-example.html#a14\">search.c</a>.</dd>\n</dl>\n</div>\n</div>\n<a class=\"anchor\" id=\"ga70e8c404d8c7ce0bbef70c2b274417cd\"></a><!-- doxytag: member=\"api.h::sp_search_is_loaded\" ref=\"ga70e8c404d8c7ce0bbef70c2b274417cd\" args=\"(sp_search *search)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\">bool sp_search_is_loaded </td>\n          <td>(</td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__types.html#gac95893a6b23d4b19f6f149eed6ead1fd\">sp_search</a> *&nbsp;</td>\n          <td class=\"paramname\"> <em>search</em></td>\n          <td>&nbsp;)&nbsp;</td>\n          <td></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Get load status for the specified search. Before it is loaded, it will behave as an empty search result.</p>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>search</em>&nbsp;</td><td>Search object</td></tr>\n  </table>\n  </dd>\n</dl>\n<dl class=\"return\"><dt><b>Returns:</b></dt><dd>True if search is loaded, otherwise false </dd></dl>\n\n</div>\n</div>\n<a class=\"anchor\" id=\"ga0c456a6396c4c05fbc8677ea641ef1f7\"></a><!-- doxytag: member=\"api.h::sp_search_num_albums\" ref=\"ga0c456a6396c4c05fbc8677ea641ef1f7\" args=\"(sp_search *search)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\">int sp_search_num_albums </td>\n          <td>(</td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__types.html#gac95893a6b23d4b19f6f149eed6ead1fd\">sp_search</a> *&nbsp;</td>\n          <td class=\"paramname\"> <em>search</em></td>\n          <td>&nbsp;)&nbsp;</td>\n          <td></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Get the number of albums for the specified search</p>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>search</em>&nbsp;</td><td>Search object</td></tr>\n  </table>\n  </dd>\n</dl>\n<dl class=\"return\"><dt><b>Returns:</b></dt><dd>The number of albums for the specified search </dd></dl>\n<dl><dt><b>Examples: </b></dt><dd><a class=\"el\" href=\"search_8c-example.html#a8\">search.c</a>.</dd>\n</dl>\n</div>\n</div>\n<a class=\"anchor\" id=\"gabd375a613c2dadecad8c13f8aca6f2d3\"></a><!-- doxytag: member=\"api.h::sp_search_num_artists\" ref=\"gabd375a613c2dadecad8c13f8aca6f2d3\" args=\"(sp_search *search)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\">int sp_search_num_artists </td>\n          <td>(</td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__types.html#gac95893a6b23d4b19f6f149eed6ead1fd\">sp_search</a> *&nbsp;</td>\n          <td class=\"paramname\"> <em>search</em></td>\n          <td>&nbsp;)&nbsp;</td>\n          <td></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Get the number of artists for the specified search</p>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>search</em>&nbsp;</td><td>Search object</td></tr>\n  </table>\n  </dd>\n</dl>\n<dl class=\"return\"><dt><b>Returns:</b></dt><dd>The number of artists for the specified search </dd></dl>\n<dl><dt><b>Examples: </b></dt><dd><a class=\"el\" href=\"search_8c-example.html#a10\">search.c</a>.</dd>\n</dl>\n</div>\n</div>\n<a class=\"anchor\" id=\"gaa9f007f439d8241bf632f9abb8d926c9\"></a><!-- doxytag: member=\"api.h::sp_search_num_playlists\" ref=\"gaa9f007f439d8241bf632f9abb8d926c9\" args=\"(sp_search *search)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\">int sp_search_num_playlists </td>\n          <td>(</td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__types.html#gac95893a6b23d4b19f6f149eed6ead1fd\">sp_search</a> *&nbsp;</td>\n          <td class=\"paramname\"> <em>search</em></td>\n          <td>&nbsp;)&nbsp;</td>\n          <td></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Get the number of playlists for the specified search</p>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>search</em>&nbsp;</td><td>Search object</td></tr>\n  </table>\n  </dd>\n</dl>\n<dl class=\"return\"><dt><b>Returns:</b></dt><dd>The number of playlists for the specified search </dd></dl>\n<dl><dt><b>Examples: </b></dt><dd><a class=\"el\" href=\"search_8c-example.html#a12\">search.c</a>.</dd>\n</dl>\n</div>\n</div>\n<a class=\"anchor\" id=\"ga1dd18cf7b3b3b7f4bf6e92a2140378d0\"></a><!-- doxytag: member=\"api.h::sp_search_num_tracks\" ref=\"ga1dd18cf7b3b3b7f4bf6e92a2140378d0\" args=\"(sp_search *search)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\">int sp_search_num_tracks </td>\n          <td>(</td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__types.html#gac95893a6b23d4b19f6f149eed6ead1fd\">sp_search</a> *&nbsp;</td>\n          <td class=\"paramname\"> <em>search</em></td>\n          <td>&nbsp;)&nbsp;</td>\n          <td></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Get the number of tracks for the specified search</p>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>search</em>&nbsp;</td><td>Search object</td></tr>\n  </table>\n  </dd>\n</dl>\n<dl class=\"return\"><dt><b>Returns:</b></dt><dd>The number of tracks for the specified search </dd></dl>\n<dl><dt><b>Examples: </b></dt><dd><a class=\"el\" href=\"search_8c-example.html#a6\">search.c</a>.</dd>\n</dl>\n</div>\n</div>\n<a class=\"anchor\" id=\"ga4175fba17f355b1c0bd361357181ea35\"></a><!-- doxytag: member=\"api.h::sp_search_playlist\" ref=\"ga4175fba17f355b1c0bd361357181ea35\" args=\"(sp_search *search, int index)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\"><a class=\"el\" href=\"group__types.html#ga1bcf54cbc117a20ab2c15e59eb3a8174\">sp_playlist</a>* sp_search_playlist </td>\n          <td>(</td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__types.html#gac95893a6b23d4b19f6f149eed6ead1fd\">sp_search</a> *&nbsp;</td>\n          <td class=\"paramname\"> <em>search</em>, </td>\n        </tr>\n        <tr>\n          <td class=\"paramkey\"></td>\n          <td></td>\n          <td class=\"paramtype\">int&nbsp;</td>\n          <td class=\"paramname\"> <em>index</em></td><td>&nbsp;</td>\n        </tr>\n        <tr>\n          <td></td>\n          <td>)</td>\n          <td></td><td></td><td></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Load the playlist at the given index in the given search object</p>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>search</em>&nbsp;</td><td>Search object </td></tr>\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>index</em>&nbsp;</td><td>Index of the wanted playlist. Should be in the interval [0, <a class=\"el\" href=\"group__search.html#gaa9f007f439d8241bf632f9abb8d926c9\">sp_search_num_playlists()</a> - 1]</td></tr>\n  </table>\n  </dd>\n</dl>\n<dl class=\"return\"><dt><b>Returns:</b></dt><dd>A playlist object. This reference is owned by the caller and should be released with <a class=\"el\" href=\"group__playlist.html#gacb9250eb530869b039541a8b62dfab6c\">sp_playlist_release()</a> </dd></dl>\n\n</div>\n</div>\n<a class=\"anchor\" id=\"gac4463fab4ea25e0a5d5079c959a1781c\"></a><!-- doxytag: member=\"api.h::sp_search_playlist_image_uri\" ref=\"gac4463fab4ea25e0a5d5079c959a1781c\" args=\"(sp_search *search, int index)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\">const char* sp_search_playlist_image_uri </td>\n          <td>(</td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__types.html#gac95893a6b23d4b19f6f149eed6ead1fd\">sp_search</a> *&nbsp;</td>\n          <td class=\"paramname\"> <em>search</em>, </td>\n        </tr>\n        <tr>\n          <td class=\"paramkey\"></td>\n          <td></td>\n          <td class=\"paramtype\">int&nbsp;</td>\n          <td class=\"paramname\"> <em>index</em></td><td>&nbsp;</td>\n        </tr>\n        <tr>\n          <td></td>\n          <td>)</td>\n          <td></td><td></td><td></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Return the image_uri of a playlist at the given index in the given search object</p>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>search</em>&nbsp;</td><td>Search object </td></tr>\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>index</em>&nbsp;</td><td>Index of the wanted playlist. Should be in the interval [0, <a class=\"el\" href=\"group__search.html#gaa9f007f439d8241bf632f9abb8d926c9\">sp_search_num_playlists()</a> - 1]</td></tr>\n  </table>\n  </dd>\n</dl>\n<dl class=\"return\"><dt><b>Returns:</b></dt><dd>The playlist image_uri at the given index in the given search object </dd></dl>\n\n</div>\n</div>\n<a class=\"anchor\" id=\"ga933cd5d5a0ccca9906082ca4549a4ed7\"></a><!-- doxytag: member=\"api.h::sp_search_playlist_name\" ref=\"ga933cd5d5a0ccca9906082ca4549a4ed7\" args=\"(sp_search *search, int index)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\">const char* sp_search_playlist_name </td>\n          <td>(</td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__types.html#gac95893a6b23d4b19f6f149eed6ead1fd\">sp_search</a> *&nbsp;</td>\n          <td class=\"paramname\"> <em>search</em>, </td>\n        </tr>\n        <tr>\n          <td class=\"paramkey\"></td>\n          <td></td>\n          <td class=\"paramtype\">int&nbsp;</td>\n          <td class=\"paramname\"> <em>index</em></td><td>&nbsp;</td>\n        </tr>\n        <tr>\n          <td></td>\n          <td>)</td>\n          <td></td><td></td><td></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Return the playlist at the given index in the given search object</p>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>search</em>&nbsp;</td><td>Search object </td></tr>\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>index</em>&nbsp;</td><td>Index of the wanted playlist. Should be in the interval [0, <a class=\"el\" href=\"group__search.html#gaa9f007f439d8241bf632f9abb8d926c9\">sp_search_num_playlists()</a> - 1]</td></tr>\n  </table>\n  </dd>\n</dl>\n<dl class=\"return\"><dt><b>Returns:</b></dt><dd>The playlist name at the given index in the given search object </dd></dl>\n<dl><dt><b>Examples: </b></dt><dd><a class=\"el\" href=\"search_8c-example.html#a13\">search.c</a>.</dd>\n</dl>\n</div>\n</div>\n<a class=\"anchor\" id=\"ga0071a3d30f0f0c4e477bf923e9014ff5\"></a><!-- doxytag: member=\"api.h::sp_search_playlist_uri\" ref=\"ga0071a3d30f0f0c4e477bf923e9014ff5\" args=\"(sp_search *search, int index)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\">const char* sp_search_playlist_uri </td>\n          <td>(</td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__types.html#gac95893a6b23d4b19f6f149eed6ead1fd\">sp_search</a> *&nbsp;</td>\n          <td class=\"paramname\"> <em>search</em>, </td>\n        </tr>\n        <tr>\n          <td class=\"paramkey\"></td>\n          <td></td>\n          <td class=\"paramtype\">int&nbsp;</td>\n          <td class=\"paramname\"> <em>index</em></td><td>&nbsp;</td>\n        </tr>\n        <tr>\n          <td></td>\n          <td>)</td>\n          <td></td><td></td><td></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Return the uri of a playlist at the given index in the given search object</p>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>search</em>&nbsp;</td><td>Search object </td></tr>\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>index</em>&nbsp;</td><td>Index of the wanted playlist. Should be in the interval [0, <a class=\"el\" href=\"group__search.html#gaa9f007f439d8241bf632f9abb8d926c9\">sp_search_num_playlists()</a> - 1]</td></tr>\n  </table>\n  </dd>\n</dl>\n<dl class=\"return\"><dt><b>Returns:</b></dt><dd>The playlist uri at the given index in the given search object </dd></dl>\n\n</div>\n</div>\n<a class=\"anchor\" id=\"ga127e9c2bf98e3602ecfc2926b9d242bf\"></a><!-- doxytag: member=\"api.h::sp_search_query\" ref=\"ga127e9c2bf98e3602ecfc2926b9d242bf\" args=\"(sp_search *search)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\">const char* sp_search_query </td>\n          <td>(</td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__types.html#gac95893a6b23d4b19f6f149eed6ead1fd\">sp_search</a> *&nbsp;</td>\n          <td class=\"paramname\"> <em>search</em></td>\n          <td>&nbsp;)&nbsp;</td>\n          <td></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Return the search query for the given search object</p>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>search</em>&nbsp;</td><td>Search object</td></tr>\n  </table>\n  </dd>\n</dl>\n<dl class=\"return\"><dt><b>Returns:</b></dt><dd>The search query for the given search object </dd></dl>\n<dl><dt><b>Examples: </b></dt><dd><a class=\"el\" href=\"search_8c-example.html#a3\">search.c</a>.</dd>\n</dl>\n</div>\n</div>\n<a class=\"anchor\" id=\"ga4e01d43067d9f8c533c985f90143821b\"></a><!-- doxytag: member=\"api.h::sp_search_release\" ref=\"ga4e01d43067d9f8c533c985f90143821b\" args=\"(sp_search *search)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\"><a class=\"el\" href=\"group__error.html#gafd27986ce4cd9eeaeca8adda83c9eb6b\">sp_error</a> sp_search_release </td>\n          <td>(</td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__types.html#gac95893a6b23d4b19f6f149eed6ead1fd\">sp_search</a> *&nbsp;</td>\n          <td class=\"paramname\"> <em>search</em></td>\n          <td>&nbsp;)&nbsp;</td>\n          <td></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Decrease the reference count of a search result</p>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>search</em>&nbsp;</td><td>The search result object </td></tr>\n  </table>\n  </dd>\n</dl>\n<dl class=\"return\"><dt><b>Returns:</b></dt><dd>One of the following errors, from <a class=\"el\" href=\"group__error.html#ga83154178d3a32668658734d2facfa22b\">sp_error</a> SP_ERROR_OK </dd></dl>\n<dl><dt><b>Examples: </b></dt><dd><a class=\"el\" href=\"search_8c-example.html#a17\">search.c</a>.</dd>\n</dl>\n</div>\n</div>\n<a class=\"anchor\" id=\"gaafd3b228adbc028937383d0d45730581\"></a><!-- doxytag: member=\"api.h::sp_search_total_albums\" ref=\"gaafd3b228adbc028937383d0d45730581\" args=\"(sp_search *search)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\">int sp_search_total_albums </td>\n          <td>(</td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__types.html#gac95893a6b23d4b19f6f149eed6ead1fd\">sp_search</a> *&nbsp;</td>\n          <td class=\"paramname\"> <em>search</em></td>\n          <td>&nbsp;)&nbsp;</td>\n          <td></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Return the total number of albums for the search query - regardless of the interval requested at creation. If this value is larger than the interval specified at creation of the search object, more search results are available. To fetch these, create a new search object with a new interval.</p>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>search</em>&nbsp;</td><td>Search object</td></tr>\n  </table>\n  </dd>\n</dl>\n<dl class=\"return\"><dt><b>Returns:</b></dt><dd>The total number of albums matching the original query </dd></dl>\n\n</div>\n</div>\n<a class=\"anchor\" id=\"ga305a4118625e0f70cfb14161a0112fd5\"></a><!-- doxytag: member=\"api.h::sp_search_total_artists\" ref=\"ga305a4118625e0f70cfb14161a0112fd5\" args=\"(sp_search *search)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\">int sp_search_total_artists </td>\n          <td>(</td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__types.html#gac95893a6b23d4b19f6f149eed6ead1fd\">sp_search</a> *&nbsp;</td>\n          <td class=\"paramname\"> <em>search</em></td>\n          <td>&nbsp;)&nbsp;</td>\n          <td></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Return the total number of artists for the search query - regardless of the interval requested at creation. If this value is larger than the interval specified at creation of the search object, more search results are available. To fetch these, create a new search object with a new interval.</p>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>search</em>&nbsp;</td><td>Search object</td></tr>\n  </table>\n  </dd>\n</dl>\n<dl class=\"return\"><dt><b>Returns:</b></dt><dd>The total number of artists matching the original query </dd></dl>\n\n</div>\n</div>\n<a class=\"anchor\" id=\"ga2e286415a6ba8dbf85ea677906f2798c\"></a><!-- doxytag: member=\"api.h::sp_search_total_playlists\" ref=\"ga2e286415a6ba8dbf85ea677906f2798c\" args=\"(sp_search *search)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\">int sp_search_total_playlists </td>\n          <td>(</td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__types.html#gac95893a6b23d4b19f6f149eed6ead1fd\">sp_search</a> *&nbsp;</td>\n          <td class=\"paramname\"> <em>search</em></td>\n          <td>&nbsp;)&nbsp;</td>\n          <td></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Return the total number of playlists for the search query - regardless of the interval requested at creation. If this value is larger than the interval specified at creation of the search object, more search results are available. To fetch these, create a new search object with a new interval.</p>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>search</em>&nbsp;</td><td>Search object</td></tr>\n  </table>\n  </dd>\n</dl>\n<dl class=\"return\"><dt><b>Returns:</b></dt><dd>The total number of playlists matching the original query </dd></dl>\n\n</div>\n</div>\n<a class=\"anchor\" id=\"gab4e50582c517b4639fd1afd6fb011587\"></a><!-- doxytag: member=\"api.h::sp_search_total_tracks\" ref=\"gab4e50582c517b4639fd1afd6fb011587\" args=\"(sp_search *search)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\">int sp_search_total_tracks </td>\n          <td>(</td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__types.html#gac95893a6b23d4b19f6f149eed6ead1fd\">sp_search</a> *&nbsp;</td>\n          <td class=\"paramname\"> <em>search</em></td>\n          <td>&nbsp;)&nbsp;</td>\n          <td></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Return the total number of tracks for the search query - regardless of the interval requested at creation. If this value is larger than the interval specified at creation of the search object, more search results are available. To fetch these, create a new search object with a new interval.</p>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>search</em>&nbsp;</td><td>Search object</td></tr>\n  </table>\n  </dd>\n</dl>\n<dl class=\"return\"><dt><b>Returns:</b></dt><dd>The total number of tracks matching the original query </dd></dl>\n<dl><dt><b>Examples: </b></dt><dd><a class=\"el\" href=\"search_8c-example.html#a5\">search.c</a>.</dd>\n</dl>\n</div>\n</div>\n<a class=\"anchor\" id=\"gae9da7ca59ce0bbd73f7bcef4e15c4da8\"></a><!-- doxytag: member=\"api.h::sp_search_track\" ref=\"gae9da7ca59ce0bbd73f7bcef4e15c4da8\" args=\"(sp_search *search, int index)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\"><a class=\"el\" href=\"group__types.html#ga47bbd2262f0c8b5d7147af7d62198e48\">sp_track</a>* sp_search_track </td>\n          <td>(</td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__types.html#gac95893a6b23d4b19f6f149eed6ead1fd\">sp_search</a> *&nbsp;</td>\n          <td class=\"paramname\"> <em>search</em>, </td>\n        </tr>\n        <tr>\n          <td class=\"paramkey\"></td>\n          <td></td>\n          <td class=\"paramtype\">int&nbsp;</td>\n          <td class=\"paramname\"> <em>index</em></td><td>&nbsp;</td>\n        </tr>\n        <tr>\n          <td></td>\n          <td>)</td>\n          <td></td><td></td><td></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Return the track at the given index in the given search object</p>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>search</em>&nbsp;</td><td>Search object </td></tr>\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>index</em>&nbsp;</td><td>Index of the wanted track. Should be in the interval [0, <a class=\"el\" href=\"group__search.html#ga1dd18cf7b3b3b7f4bf6e92a2140378d0\">sp_search_num_tracks()</a> - 1]</td></tr>\n  </table>\n  </dd>\n</dl>\n<dl class=\"return\"><dt><b>Returns:</b></dt><dd>The track at the given index in the given search object </dd></dl>\n<dl><dt><b>Examples: </b></dt><dd><a class=\"el\" href=\"search_8c-example.html#a7\">search.c</a>.</dd>\n</dl>\n</div>\n</div>\n</div>\n<hr size=\"1\"><address style=\"text-align: right;\"><small>\nGenerated on Wed Jun 13 2012 14:22:40.<br>\nCopyright &copy; 2006&ndash;2012 Spotify Ltd</small></address>\n</body>\n</html>\n"
  },
  {
    "path": "libspotify/docs/html/group__session.html",
    "content": "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\n<html xmlns=\"http://www.w3.org/1999/xhtml\">\n<head>\n<meta http-equiv=\"Content-Type\" content=\"text/xhtml;charset=UTF-8\"/>\n<title>libspotify: Session handling</title>\n<link href=\"tabs.css\" rel=\"stylesheet\" type=\"text/css\"/>\n<link href=\"doxygen.css\" rel=\"stylesheet\" type=\"text/css\"/>\n</head>\n<body>\n<!-- Generated by Doxygen 1.7.1 -->\n<div class=\"navigation\" id=\"top\">\n  <div class=\"tabs\">\n    <ul class=\"tablist\">\n      <li><a href=\"index.html\"><span>Main&nbsp;Page</span></a></li>\n      <li><a href=\"modules.html\"><span>Modules</span></a></li>\n      <li><a href=\"annotated.html\"><span>Data&nbsp;Structures</span></a></li>\n      <li><a href=\"files.html\"><span>Files</span></a></li>\n      <li><a href=\"examples.html\"><span>Examples</span></a></li>\n    </ul>\n  </div>\n</div>\n<div class=\"header\">\n  <div class=\"summary\">\n<a href=\"#nested-classes\">Data Structures</a> &#124;\n<a href=\"#define-members\">Defines</a> &#124;\n<a href=\"#typedef-members\">Typedefs</a> &#124;\n<a href=\"#enum-members\">Enumerations</a> &#124;\n<a href=\"#func-members\">Functions</a>  </div>\n  <div class=\"headertitle\">\n<h1>Session handling</h1>  </div>\n</div>\n<div class=\"contents\">\n<table class=\"memberdecls\">\n<tr><td colspan=\"2\"><h2><a name=\"nested-classes\"></a>\nData Structures</h2></td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">struct &nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"structsp__audioformat.html\">sp_audioformat</a></td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">struct &nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"structsp__audio__buffer__stats.html\">sp_audio_buffer_stats</a></td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">struct &nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"structsp__subscribers.html\">sp_subscribers</a></td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">struct &nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"structsp__offline__sync__status.html\">sp_offline_sync_status</a></td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">struct &nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"structsp__session__callbacks.html\">sp_session_callbacks</a></td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">struct &nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"structsp__session__config.html\">sp_session_config</a></td></tr>\n<tr><td colspan=\"2\"><h2><a name=\"define-members\"></a>\nDefines</h2></td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">#define&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__session.html#ga63b2309874193750ec3395f6cae32899\">SPOTIFY_API_VERSION</a>&nbsp;&nbsp;&nbsp;12</td></tr>\n<tr><td colspan=\"2\"><h2><a name=\"typedef-members\"></a>\nTypedefs</h2></td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">typedef enum <a class=\"el\" href=\"group__session.html#gabf77bb5a124d5a6ee9a12c86abbc0d34\">sp_connectionstate</a>&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__session.html#gac0fa3d4cc60bd2e3d666026f88980e8c\">sp_connectionstate</a></td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">typedef enum <a class=\"el\" href=\"group__session.html#ga087d21080010768316cfb55d938eb94d\">sp_sampletype</a>&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__session.html#ga5ef462e78d5a5af60dd0e7085b1ba512\">sp_sampletype</a></td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">typedef struct <a class=\"el\" href=\"structsp__audioformat.html\">sp_audioformat</a>&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__session.html#ga5338d4a10576ba8d6ab11b70892d503c\">sp_audioformat</a></td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">typedef enum <a class=\"el\" href=\"group__session.html#ga77ddd919314a7bb16140569af7a38fe2\">sp_bitrate</a>&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__session.html#ga83d3de45241a44e787410993c5fac0ea\">sp_bitrate</a></td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">typedef enum <a class=\"el\" href=\"group__session.html#gafdd7117213605e6f2671c4f289b44609\">sp_playlist_type</a>&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__session.html#ga86723f553db2db6a8f507cd748948ad4\">sp_playlist_type</a></td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">typedef enum <a class=\"el\" href=\"group__session.html#ga99e8e9176ce40fff08a9be8b944edb09\">sp_search_type</a>&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__session.html#ga647e4de81e5ac0a2e5d1193b1005ed3e\">sp_search_type</a></td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">typedef enum <br class=\"typebreak\"/>\n<a class=\"el\" href=\"group__session.html#ga811fa52ed0fdb5cda732682e27e40417\">sp_playlist_offline_status</a>&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__session.html#gac507efa32e8c122fbe9ea41d96180d06\">sp_playlist_offline_status</a></td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">typedef enum <a class=\"el\" href=\"group__session.html#gad7d9465769597b2a379ac704099adfdf\">sp_availability</a>&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__session.html#ga60c7ff53ddbc04c036a23181b7275d69\">sp_track_availability</a></td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">typedef enum <br class=\"typebreak\"/>\n<a class=\"el\" href=\"group__session.html#gaeaa41aad3c0047409996a6ec3b03203f\">sp_track_offline_status</a>&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__session.html#gae689044941537050de641a1dcd4c75d5\">sp_track_offline_status</a></td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">typedef enum <a class=\"el\" href=\"group__session.html#ga61bc424465d776af3ceeb69eee2bb492\">sp_image_size</a>&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__session.html#gaca320fd41bd0556b7fa1f2fa6e14faee\">sp_image_size</a></td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">typedef struct <br class=\"typebreak\"/>\n<a class=\"el\" href=\"structsp__audio__buffer__stats.html\">sp_audio_buffer_stats</a>&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__session.html#ga25462859a596a247ba5cc1853fc32cca\">sp_audio_buffer_stats</a></td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">typedef struct <a class=\"el\" href=\"structsp__subscribers.html\">sp_subscribers</a>&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__session.html#gafb515e30d134c61b8eaaff3177af0b5b\">sp_subscribers</a></td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">typedef enum <a class=\"el\" href=\"group__session.html#ga3e8773baeb94189b9a1ff27d6a5e3553\">sp_connection_type</a>&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__session.html#ga05a7dbb946a9c47bf011f3f3d77964c3\">sp_connection_type</a></td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">typedef enum <a class=\"el\" href=\"group__session.html#gad275d696685b2ad9ff1a2c3e16af6502\">sp_connection_rules</a>&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__session.html#ga24ee483cdceef9af3b415c020b197a75\">sp_connection_rules</a></td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">typedef enum <a class=\"el\" href=\"group__session.html#gac86504cc9e8cadbc30c8aa8dbf355034\">sp_artistbrowse_type</a>&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__session.html#gab947eba77c176504c69cbb2f1de9830d\">sp_artistbrowse_type</a></td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">typedef struct <br class=\"typebreak\"/>\n<a class=\"el\" href=\"structsp__offline__sync__status.html\">sp_offline_sync_status</a>&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__session.html#gaa7f24f13d6d105869c405045a4cc2a20\">sp_offline_sync_status</a></td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">typedef struct <a class=\"el\" href=\"structsp__session__callbacks.html\">sp_session_callbacks</a>&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__session.html#gaf1d92302cd5d0d4a032e1408188c8fd5\">sp_session_callbacks</a></td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">typedef struct <a class=\"el\" href=\"structsp__session__config.html\">sp_session_config</a>&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__session.html#ga372b25a93da38d4d707b0c2eaa7b3ebb\">sp_session_config</a></td></tr>\n<tr><td colspan=\"2\"><h2><a name=\"enum-members\"></a>\nEnumerations</h2></td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">enum &nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__session.html#gabf77bb5a124d5a6ee9a12c86abbc0d34\">sp_connectionstate</a> { <br/>\n&nbsp;&nbsp;<a class=\"el\" href=\"group__session.html#ggabf77bb5a124d5a6ee9a12c86abbc0d34ae31e9958a98211ecff5ecbcf7041dfa5\">SP_CONNECTION_STATE_LOGGED_OUT</a> =  0, \n<br/>\n&nbsp;&nbsp;<a class=\"el\" href=\"group__session.html#ggabf77bb5a124d5a6ee9a12c86abbc0d34a88ae17b4168184e62e4c190c289c47c5\">SP_CONNECTION_STATE_LOGGED_IN</a> =  1, \n<br/>\n&nbsp;&nbsp;<a class=\"el\" href=\"group__session.html#ggabf77bb5a124d5a6ee9a12c86abbc0d34ad1a6eb721675af4613f823c091538a8c\">SP_CONNECTION_STATE_DISCONNECTED</a> =  2, \n<br/>\n&nbsp;&nbsp;<a class=\"el\" href=\"group__session.html#ggabf77bb5a124d5a6ee9a12c86abbc0d34a4ddf57518007eef86b06f496d7059484\">SP_CONNECTION_STATE_UNDEFINED</a> =  3, \n<br/>\n&nbsp;&nbsp;<a class=\"el\" href=\"group__session.html#ggabf77bb5a124d5a6ee9a12c86abbc0d34a63099ef9185ba287fcd2e77be3c47d8f\">SP_CONNECTION_STATE_OFFLINE</a> =  4\n<br/>\n }</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">enum &nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__session.html#ga087d21080010768316cfb55d938eb94d\">sp_sampletype</a> { <a class=\"el\" href=\"group__session.html#gga087d21080010768316cfb55d938eb94daa829b269d191cca95ecb02c2bc59da42\">SP_SAMPLETYPE_INT16_NATIVE_ENDIAN</a> =  0\n }</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">enum &nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__session.html#ga77ddd919314a7bb16140569af7a38fe2\">sp_bitrate</a> { <br/>\n&nbsp;&nbsp;<a class=\"el\" href=\"group__session.html#gga77ddd919314a7bb16140569af7a38fe2a5b5c794224972f833a4b7eec9d7909c9\">SP_BITRATE_160k</a> =  0, \n<br/>\n&nbsp;&nbsp;<a class=\"el\" href=\"group__session.html#gga77ddd919314a7bb16140569af7a38fe2a9383c0dc9faefd2cbb38c3b9342c47e0\">SP_BITRATE_320k</a> =  1, \n<br/>\n&nbsp;&nbsp;<a class=\"el\" href=\"group__session.html#gga77ddd919314a7bb16140569af7a38fe2ad815a35af7e6bb5e2ef29418af62759b\">SP_BITRATE_96k</a> =  2\n<br/>\n }</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">enum &nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__session.html#gafdd7117213605e6f2671c4f289b44609\">sp_playlist_type</a> { <br/>\n&nbsp;&nbsp;<a class=\"el\" href=\"group__session.html#ggafdd7117213605e6f2671c4f289b44609a6bd6bf9b62018fa9bbf969835c2f3077\">SP_PLAYLIST_TYPE_PLAYLIST</a> =  0, \n<br/>\n&nbsp;&nbsp;<a class=\"el\" href=\"group__session.html#ggafdd7117213605e6f2671c4f289b44609a4d3266991787f9438deb9de83d9200da\">SP_PLAYLIST_TYPE_START_FOLDER</a> =  1, \n<br/>\n&nbsp;&nbsp;<a class=\"el\" href=\"group__session.html#ggafdd7117213605e6f2671c4f289b44609a3ec52ad1d99d8e32e1b9de31e3f5187a\">SP_PLAYLIST_TYPE_END_FOLDER</a> =  2, \n<br/>\n&nbsp;&nbsp;<a class=\"el\" href=\"group__session.html#ggafdd7117213605e6f2671c4f289b44609ad4f860ef76154e3e2c0d9da2f57a2784\">SP_PLAYLIST_TYPE_PLACEHOLDER</a> =  3\n<br/>\n }</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">enum &nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__session.html#ga99e8e9176ce40fff08a9be8b944edb09\">sp_search_type</a> </td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">enum &nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__session.html#ga811fa52ed0fdb5cda732682e27e40417\">sp_playlist_offline_status</a> { <br/>\n&nbsp;&nbsp;<a class=\"el\" href=\"group__session.html#gga811fa52ed0fdb5cda732682e27e40417abef62e4e3a4af8827fed7fe3aa733ca0\">SP_PLAYLIST_OFFLINE_STATUS_NO</a> =  0, \n<br/>\n&nbsp;&nbsp;<a class=\"el\" href=\"group__session.html#gga811fa52ed0fdb5cda732682e27e40417affed38ac820e084b96fb48e3d1939584\">SP_PLAYLIST_OFFLINE_STATUS_YES</a> =  1, \n<br/>\n&nbsp;&nbsp;<a class=\"el\" href=\"group__session.html#gga811fa52ed0fdb5cda732682e27e40417abc999c70761d392b26753708e9a2cfa1\">SP_PLAYLIST_OFFLINE_STATUS_DOWNLOADING</a> =  2, \n<br/>\n&nbsp;&nbsp;<a class=\"el\" href=\"group__session.html#gga811fa52ed0fdb5cda732682e27e40417a7d929bbf4f1df3633b283e39b9c95919\">SP_PLAYLIST_OFFLINE_STATUS_WAITING</a> =  3\n<br/>\n }</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">enum &nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__session.html#gad7d9465769597b2a379ac704099adfdf\">sp_availability</a> { <br/>\n&nbsp;&nbsp;<a class=\"el\" href=\"group__session.html#ggad7d9465769597b2a379ac704099adfdfa44bc1e6f138910b3f8dbd309325e0077\">SP_TRACK_AVAILABILITY_UNAVAILABLE</a> =  0, \n<br/>\n&nbsp;&nbsp;<a class=\"el\" href=\"group__session.html#ggad7d9465769597b2a379ac704099adfdfa3b837ba6d740b5650b0113734a3b2ff7\">SP_TRACK_AVAILABILITY_AVAILABLE</a> =  1, \n<br/>\n&nbsp;&nbsp;<a class=\"el\" href=\"group__session.html#ggad7d9465769597b2a379ac704099adfdfae7b2cfafa10288ecc50df97621bbe940\">SP_TRACK_AVAILABILITY_NOT_STREAMABLE</a> =  2, \n<br/>\n&nbsp;&nbsp;<a class=\"el\" href=\"group__session.html#ggad7d9465769597b2a379ac704099adfdfaeb5d63e89c543f513cd3054969e50914\">SP_TRACK_AVAILABILITY_BANNED_BY_ARTIST</a> =  3\n<br/>\n }</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">enum &nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__session.html#gaeaa41aad3c0047409996a6ec3b03203f\">sp_track_offline_status</a> { <br/>\n&nbsp;&nbsp;<a class=\"el\" href=\"group__session.html#ggaeaa41aad3c0047409996a6ec3b03203faad1a1cba82ce9f9be678f4d1042eddec\">SP_TRACK_OFFLINE_NO</a> =  0, \n<br/>\n&nbsp;&nbsp;<a class=\"el\" href=\"group__session.html#ggaeaa41aad3c0047409996a6ec3b03203fa1fdd2a518dcdc072cfca27a0ca4f2581\">SP_TRACK_OFFLINE_WAITING</a> =  1, \n<br/>\n&nbsp;&nbsp;<a class=\"el\" href=\"group__session.html#ggaeaa41aad3c0047409996a6ec3b03203fa7dcf6dfc56a8421200451d07a476f370\">SP_TRACK_OFFLINE_DOWNLOADING</a> =  2, \n<br/>\n&nbsp;&nbsp;<a class=\"el\" href=\"group__session.html#ggaeaa41aad3c0047409996a6ec3b03203fac54d46cbc73de7686a1ad8daf269532a\">SP_TRACK_OFFLINE_DONE</a> =  3, \n<br/>\n&nbsp;&nbsp;<a class=\"el\" href=\"group__session.html#ggaeaa41aad3c0047409996a6ec3b03203fa86618798c266540bdc889dd037a52631\">SP_TRACK_OFFLINE_ERROR</a> =  4, \n<br/>\n&nbsp;&nbsp;<a class=\"el\" href=\"group__session.html#ggaeaa41aad3c0047409996a6ec3b03203fa00fe430030fb6a8a49a46c11cca7326c\">SP_TRACK_OFFLINE_DONE_EXPIRED</a> =  5, \n<br/>\n&nbsp;&nbsp;<a class=\"el\" href=\"group__session.html#ggaeaa41aad3c0047409996a6ec3b03203fa405a9b7a3fa489ad2dadbb108794e247\">SP_TRACK_OFFLINE_LIMIT_EXCEEDED</a> =  6, \n<br/>\n&nbsp;&nbsp;<a class=\"el\" href=\"group__session.html#ggaeaa41aad3c0047409996a6ec3b03203fa5f3e19627de4509ae4a3864fd29edee6\">SP_TRACK_OFFLINE_DONE_RESYNC</a> =  7\n<br/>\n }</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">enum &nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__session.html#ga61bc424465d776af3ceeb69eee2bb492\">sp_image_size</a> { <br/>\n&nbsp;&nbsp;<a class=\"el\" href=\"group__session.html#gga61bc424465d776af3ceeb69eee2bb492ad20c808fd1f8180d1f49f643975d1dd7\">SP_IMAGE_SIZE_NORMAL</a> =  0, \n<br/>\n&nbsp;&nbsp;<a class=\"el\" href=\"group__session.html#gga61bc424465d776af3ceeb69eee2bb492ab9340b1bcf2129c3ad1328ea617d547f\">SP_IMAGE_SIZE_SMALL</a> =  1, \n<br/>\n&nbsp;&nbsp;<a class=\"el\" href=\"group__session.html#gga61bc424465d776af3ceeb69eee2bb492a0a0b624afbb2a66ee3d7954202b89721\">SP_IMAGE_SIZE_LARGE</a> =  2\n<br/>\n }</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">enum &nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__session.html#ga3e8773baeb94189b9a1ff27d6a5e3553\">sp_connection_type</a> { <br/>\n&nbsp;&nbsp;<a class=\"el\" href=\"group__session.html#gga3e8773baeb94189b9a1ff27d6a5e3553af949fae9bc12f47b99ef290fa9b5d8a7\">SP_CONNECTION_TYPE_UNKNOWN</a> =  0, \n<br/>\n&nbsp;&nbsp;<a class=\"el\" href=\"group__session.html#gga3e8773baeb94189b9a1ff27d6a5e3553aa7aae7ae3f7c471ece1c6aa2705d046c\">SP_CONNECTION_TYPE_NONE</a> =  1, \n<br/>\n&nbsp;&nbsp;<a class=\"el\" href=\"group__session.html#gga3e8773baeb94189b9a1ff27d6a5e3553a3ca3e6a85ac9d497914c35620ad5179d\">SP_CONNECTION_TYPE_MOBILE</a> =  2, \n<br/>\n&nbsp;&nbsp;<a class=\"el\" href=\"group__session.html#gga3e8773baeb94189b9a1ff27d6a5e3553a05b41bbfd369f9030a7daafc9395116e\">SP_CONNECTION_TYPE_MOBILE_ROAMING</a> =  3, \n<br/>\n&nbsp;&nbsp;<a class=\"el\" href=\"group__session.html#gga3e8773baeb94189b9a1ff27d6a5e3553a31d2cad7379f1bc2eeedd24c40541cb9\">SP_CONNECTION_TYPE_WIFI</a> =  4, \n<br/>\n&nbsp;&nbsp;<a class=\"el\" href=\"group__session.html#gga3e8773baeb94189b9a1ff27d6a5e3553a4f9f0c09e59af4114bb369ebcc474710\">SP_CONNECTION_TYPE_WIRED</a> =  5\n<br/>\n }</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">enum &nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__session.html#gad275d696685b2ad9ff1a2c3e16af6502\">sp_connection_rules</a> { <br/>\n&nbsp;&nbsp;<a class=\"el\" href=\"group__session.html#ggad275d696685b2ad9ff1a2c3e16af6502aa39a1c21c17c55cd1547bc900ae2d386\">SP_CONNECTION_RULE_NETWORK</a> =  0x1, \n<br/>\n&nbsp;&nbsp;<a class=\"el\" href=\"group__session.html#ggad275d696685b2ad9ff1a2c3e16af6502af2772ba84ee7e410ad99708a11955670\">SP_CONNECTION_RULE_NETWORK_IF_ROAMING</a> =  0x2, \n<br/>\n&nbsp;&nbsp;<a class=\"el\" href=\"group__session.html#ggad275d696685b2ad9ff1a2c3e16af6502a91a946573c44de44d74e9d20dbce4c74\">SP_CONNECTION_RULE_ALLOW_SYNC_OVER_MOBILE</a> =  0x4, \n<br/>\n&nbsp;&nbsp;<a class=\"el\" href=\"group__session.html#ggad275d696685b2ad9ff1a2c3e16af6502a548f3734832ec65a992e598d8b91633d\">SP_CONNECTION_RULE_ALLOW_SYNC_OVER_WIFI</a> =  0x8\n<br/>\n }</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">enum &nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__session.html#gac86504cc9e8cadbc30c8aa8dbf355034\">sp_artistbrowse_type</a> { <br/>\n&nbsp;&nbsp;<a class=\"el\" href=\"group__session.html#ggac86504cc9e8cadbc30c8aa8dbf355034a2914168528aded818177c013a0dd7e87\">SP_ARTISTBROWSE_FULL</a>, \n<br/>\n&nbsp;&nbsp;<a class=\"el\" href=\"group__session.html#ggac86504cc9e8cadbc30c8aa8dbf355034afbad1e58606b3230dce5bc3320c95d12\">SP_ARTISTBROWSE_NO_TRACKS</a>, \n<br/>\n&nbsp;&nbsp;<a class=\"el\" href=\"group__session.html#ggac86504cc9e8cadbc30c8aa8dbf355034ac0032981f8dbf44c022e6a7ab1672167\">SP_ARTISTBROWSE_NO_ALBUMS</a>\n<br/>\n }</td></tr>\n<tr><td colspan=\"2\"><h2><a name=\"func-members\"></a>\nFunctions</h2></td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__error.html#gafd27986ce4cd9eeaeca8adda83c9eb6b\">sp_error</a>&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__session.html#gaf2891f2daced4ff6da84219d6376b3aa\">sp_session_create</a> (const <a class=\"el\" href=\"structsp__session__config.html\">sp_session_config</a> *config, <a class=\"el\" href=\"group__types.html#ga70dd19c6f824cf6a159575aa4c128b53\">sp_session</a> **sess)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__error.html#gafd27986ce4cd9eeaeca8adda83c9eb6b\">sp_error</a>&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__session.html#gab81c540b76f7425a9cc0dbf270c09674\">sp_session_release</a> (<a class=\"el\" href=\"group__types.html#ga70dd19c6f824cf6a159575aa4c128b53\">sp_session</a> *sess)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__error.html#gafd27986ce4cd9eeaeca8adda83c9eb6b\">sp_error</a>&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__session.html#ga4533a992a120cacb109c892a852afe2a\">sp_session_login</a> (<a class=\"el\" href=\"group__types.html#ga70dd19c6f824cf6a159575aa4c128b53\">sp_session</a> *session, const char *username, const char *password, bool remember_me, const char *blob)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__error.html#gafd27986ce4cd9eeaeca8adda83c9eb6b\">sp_error</a>&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__session.html#gae1bc9bebd230226c3d48925cd1be6edf\">sp_session_relogin</a> (<a class=\"el\" href=\"group__types.html#ga70dd19c6f824cf6a159575aa4c128b53\">sp_session</a> *session)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">int&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__session.html#gab349c7bfe59e10e167bd75c20df9fc97\">sp_session_remembered_user</a> (<a class=\"el\" href=\"group__types.html#ga70dd19c6f824cf6a159575aa4c128b53\">sp_session</a> *session, char *buffer, size_t buffer_size)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">const char *&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__session.html#gac7a365c2166738909cdb901edebc3f70\">sp_session_user_name</a> (<a class=\"el\" href=\"group__types.html#ga70dd19c6f824cf6a159575aa4c128b53\">sp_session</a> *session)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__error.html#gafd27986ce4cd9eeaeca8adda83c9eb6b\">sp_error</a>&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__session.html#ga61e6b796d9e07682c018e888b901a191\">sp_session_forget_me</a> (<a class=\"el\" href=\"group__types.html#ga70dd19c6f824cf6a159575aa4c128b53\">sp_session</a> *session)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__types.html#gaed2dbaa1eebd6752f76613daad9158bc\">sp_user</a> *&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__session.html#ga267bbcae24b6bb1fd56de56678a5f455\">sp_session_user</a> (<a class=\"el\" href=\"group__types.html#ga70dd19c6f824cf6a159575aa4c128b53\">sp_session</a> *session)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__error.html#gafd27986ce4cd9eeaeca8adda83c9eb6b\">sp_error</a>&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__session.html#gab7f08ca0939985b30ae2d1ed9db1d726\">sp_session_logout</a> (<a class=\"el\" href=\"group__types.html#ga70dd19c6f824cf6a159575aa4c128b53\">sp_session</a> *session)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__error.html#gafd27986ce4cd9eeaeca8adda83c9eb6b\">sp_error</a>&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__session.html#ga34005bb06ee3de8ee4221597a0335cca\">sp_session_flush_caches</a> (<a class=\"el\" href=\"group__types.html#ga70dd19c6f824cf6a159575aa4c128b53\">sp_session</a> *session)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__session.html#gabf77bb5a124d5a6ee9a12c86abbc0d34\">sp_connectionstate</a>&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__session.html#ga34a7c9527705ab7d23b742006d81ea35\">sp_session_connectionstate</a> (<a class=\"el\" href=\"group__types.html#ga70dd19c6f824cf6a159575aa4c128b53\">sp_session</a> *session)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">void *&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__session.html#gabfb3f59b20ae0b225e154eb9095152b2\">sp_session_userdata</a> (<a class=\"el\" href=\"group__types.html#ga70dd19c6f824cf6a159575aa4c128b53\">sp_session</a> *session)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__error.html#gafd27986ce4cd9eeaeca8adda83c9eb6b\">sp_error</a>&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__session.html#ga6f27c55d1ce9f3f794fcce7bee7adfea\">sp_session_set_cache_size</a> (<a class=\"el\" href=\"group__types.html#ga70dd19c6f824cf6a159575aa4c128b53\">sp_session</a> *session, size_t size)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__error.html#gafd27986ce4cd9eeaeca8adda83c9eb6b\">sp_error</a>&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__session.html#gaff27cb730db6debf55e750e39e7fadd7\">sp_session_process_events</a> (<a class=\"el\" href=\"group__types.html#ga70dd19c6f824cf6a159575aa4c128b53\">sp_session</a> *session, int *next_timeout)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__error.html#gafd27986ce4cd9eeaeca8adda83c9eb6b\">sp_error</a>&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__session.html#gac73bf2c569a43d824439b557d5e4b293\">sp_session_player_load</a> (<a class=\"el\" href=\"group__types.html#ga70dd19c6f824cf6a159575aa4c128b53\">sp_session</a> *session, <a class=\"el\" href=\"group__types.html#ga47bbd2262f0c8b5d7147af7d62198e48\">sp_track</a> *track)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__error.html#gafd27986ce4cd9eeaeca8adda83c9eb6b\">sp_error</a>&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__session.html#ga3430cd4f11541868d3f83eaa31aecf44\">sp_session_player_seek</a> (<a class=\"el\" href=\"group__types.html#ga70dd19c6f824cf6a159575aa4c128b53\">sp_session</a> *session, int offset)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__error.html#gafd27986ce4cd9eeaeca8adda83c9eb6b\">sp_error</a>&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__session.html#gab66c5915967e4f90db945b118e620624\">sp_session_player_play</a> (<a class=\"el\" href=\"group__types.html#ga70dd19c6f824cf6a159575aa4c128b53\">sp_session</a> *session, bool play)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__error.html#gafd27986ce4cd9eeaeca8adda83c9eb6b\">sp_error</a>&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__session.html#gafa7ee2803f119451bb8be3bf28746975\">sp_session_player_unload</a> (<a class=\"el\" href=\"group__types.html#ga70dd19c6f824cf6a159575aa4c128b53\">sp_session</a> *session)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__error.html#gafd27986ce4cd9eeaeca8adda83c9eb6b\">sp_error</a>&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__session.html#gaf42e30a1f430ac7c436c7d9f0485368d\">sp_session_player_prefetch</a> (<a class=\"el\" href=\"group__types.html#ga70dd19c6f824cf6a159575aa4c128b53\">sp_session</a> *session, <a class=\"el\" href=\"group__types.html#ga47bbd2262f0c8b5d7147af7d62198e48\">sp_track</a> *track)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__types.html#ga45a2febbe167483e48dab8d606d462d7\">sp_playlistcontainer</a> *&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__session.html#ga319767f0b795f1c46a08390b587c5671\">sp_session_playlistcontainer</a> (<a class=\"el\" href=\"group__types.html#ga70dd19c6f824cf6a159575aa4c128b53\">sp_session</a> *session)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__types.html#ga1bcf54cbc117a20ab2c15e59eb3a8174\">sp_playlist</a> *&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__session.html#gac72ccb51031c846101134b73195bb9ec\">sp_session_inbox_create</a> (<a class=\"el\" href=\"group__types.html#ga70dd19c6f824cf6a159575aa4c128b53\">sp_session</a> *session)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__types.html#ga1bcf54cbc117a20ab2c15e59eb3a8174\">sp_playlist</a> *&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__session.html#ga02391c9e28cff0a602f7139542e0238f\">sp_session_starred_create</a> (<a class=\"el\" href=\"group__types.html#ga70dd19c6f824cf6a159575aa4c128b53\">sp_session</a> *session)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__types.html#ga1bcf54cbc117a20ab2c15e59eb3a8174\">sp_playlist</a> *&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__session.html#ga9be806a719a6399bfe1fd0d4c125e0eb\">sp_session_starred_for_user_create</a> (<a class=\"el\" href=\"group__types.html#ga70dd19c6f824cf6a159575aa4c128b53\">sp_session</a> *session, const char *canonical_username)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__types.html#ga45a2febbe167483e48dab8d606d462d7\">sp_playlistcontainer</a> *&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__session.html#ga4ad3a1de596a41f275120dad3bb4685d\">sp_session_publishedcontainer_for_user_create</a> (<a class=\"el\" href=\"group__types.html#ga70dd19c6f824cf6a159575aa4c128b53\">sp_session</a> *session, const char *canonical_username)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__error.html#gafd27986ce4cd9eeaeca8adda83c9eb6b\">sp_error</a>&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__session.html#gacd590e095b011af42fb10046117846fe\">sp_session_preferred_bitrate</a> (<a class=\"el\" href=\"group__types.html#ga70dd19c6f824cf6a159575aa4c128b53\">sp_session</a> *session, <a class=\"el\" href=\"group__session.html#ga77ddd919314a7bb16140569af7a38fe2\">sp_bitrate</a> bitrate)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__error.html#gafd27986ce4cd9eeaeca8adda83c9eb6b\">sp_error</a>&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__session.html#ga4bba5f828d6c87692f2c355cc8f07c61\">sp_session_preferred_offline_bitrate</a> (<a class=\"el\" href=\"group__types.html#ga70dd19c6f824cf6a159575aa4c128b53\">sp_session</a> *session, <a class=\"el\" href=\"group__session.html#ga77ddd919314a7bb16140569af7a38fe2\">sp_bitrate</a> bitrate, bool allow_resync)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">bool&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__session.html#ga7913df06394360f255c77fb87af0f1fe\">sp_session_get_volume_normalization</a> (<a class=\"el\" href=\"group__types.html#ga70dd19c6f824cf6a159575aa4c128b53\">sp_session</a> *session)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__error.html#gafd27986ce4cd9eeaeca8adda83c9eb6b\">sp_error</a>&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__session.html#ga4e14f58356d00e3693be84623bf6bd11\">sp_session_set_volume_normalization</a> (<a class=\"el\" href=\"group__types.html#ga70dd19c6f824cf6a159575aa4c128b53\">sp_session</a> *session, bool on)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__error.html#gafd27986ce4cd9eeaeca8adda83c9eb6b\">sp_error</a>&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__session.html#ga42a8f0999316ac7f141926092879ad2f\">sp_session_set_private_session</a> (<a class=\"el\" href=\"group__types.html#ga70dd19c6f824cf6a159575aa4c128b53\">sp_session</a> *session, bool enabled)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">bool&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__session.html#ga72702ee06bc96c074804388d24344149\">sp_session_is_private_session</a> (<a class=\"el\" href=\"group__types.html#ga70dd19c6f824cf6a159575aa4c128b53\">sp_session</a> *session)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__error.html#gafd27986ce4cd9eeaeca8adda83c9eb6b\">sp_error</a>&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__session.html#ga2475a1fbc2eeacccb96b7f36efd36725\">sp_session_set_scrobbling</a> (<a class=\"el\" href=\"group__types.html#ga70dd19c6f824cf6a159575aa4c128b53\">sp_session</a> *session, sp_social_provider provider, sp_scrobbling_state state)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__error.html#gafd27986ce4cd9eeaeca8adda83c9eb6b\">sp_error</a>&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__session.html#ga6a56bc82ff0b369bb6e0f035534ce33d\">sp_session_is_scrobbling</a> (<a class=\"el\" href=\"group__types.html#ga70dd19c6f824cf6a159575aa4c128b53\">sp_session</a> *session, sp_social_provider provider, sp_scrobbling_state *state)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__error.html#gafd27986ce4cd9eeaeca8adda83c9eb6b\">sp_error</a>&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__session.html#ga0fad03ceabcf8d68af78f0f35fcbcc8d\">sp_session_is_scrobbling_possible</a> (<a class=\"el\" href=\"group__types.html#ga70dd19c6f824cf6a159575aa4c128b53\">sp_session</a> *session, sp_social_provider provider, bool *out)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__error.html#gafd27986ce4cd9eeaeca8adda83c9eb6b\">sp_error</a>&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__session.html#ga9e5ee46ef5e75aa462607caac984f2de\">sp_session_set_social_credentials</a> (<a class=\"el\" href=\"group__types.html#ga70dd19c6f824cf6a159575aa4c128b53\">sp_session</a> *session, sp_social_provider provider, const char *username, const char *password)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__error.html#gafd27986ce4cd9eeaeca8adda83c9eb6b\">sp_error</a>&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__session.html#gaf81c61799e0ccdbba048fb79ec050930\">sp_session_set_connection_type</a> (<a class=\"el\" href=\"group__types.html#ga70dd19c6f824cf6a159575aa4c128b53\">sp_session</a> *session, <a class=\"el\" href=\"group__session.html#ga3e8773baeb94189b9a1ff27d6a5e3553\">sp_connection_type</a> type)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__error.html#gafd27986ce4cd9eeaeca8adda83c9eb6b\">sp_error</a>&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__session.html#ga0ac85299c37710321b6d64713e1d6ba8\">sp_session_set_connection_rules</a> (<a class=\"el\" href=\"group__types.html#ga70dd19c6f824cf6a159575aa4c128b53\">sp_session</a> *session, <a class=\"el\" href=\"group__session.html#gad275d696685b2ad9ff1a2c3e16af6502\">sp_connection_rules</a> rules)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">int&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__session.html#gaf535124b4208c279cb98a061834e6411\">sp_offline_tracks_to_sync</a> (<a class=\"el\" href=\"group__types.html#ga70dd19c6f824cf6a159575aa4c128b53\">sp_session</a> *session)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">int&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__session.html#gad6cee58fa44453b7a4fd2ae2266df055\">sp_offline_num_playlists</a> (<a class=\"el\" href=\"group__types.html#ga70dd19c6f824cf6a159575aa4c128b53\">sp_session</a> *session)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">bool&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__session.html#ga02525cd659a34728047cd3801049e822\">sp_offline_sync_get_status</a> (<a class=\"el\" href=\"group__types.html#ga70dd19c6f824cf6a159575aa4c128b53\">sp_session</a> *session, <a class=\"el\" href=\"structsp__offline__sync__status.html\">sp_offline_sync_status</a> *status)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">int&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__session.html#gac36816dc42825db9a5a2fbd2694f20af\">sp_offline_time_left</a> (<a class=\"el\" href=\"group__types.html#ga70dd19c6f824cf6a159575aa4c128b53\">sp_session</a> *session)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">int&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__session.html#ga54c7693afa9be664f3ea870feb0df8d9\">sp_session_user_country</a> (<a class=\"el\" href=\"group__types.html#ga70dd19c6f824cf6a159575aa4c128b53\">sp_session</a> *session)</td></tr>\n</table>\n<hr/><a name=\"_details\"></a><h2>Detailed Description</h2>\n<p>The concept of a session is fundamental for all communication with the Spotify ecosystem - it is the object responsible for communicating with the Spotify service. You will need to instantiate a session that then can be used to request artist information, perform searches etc. </p>\n<hr/><h2>Define Documentation</h2>\n<a class=\"anchor\" id=\"ga63b2309874193750ec3395f6cae32899\"></a><!-- doxytag: member=\"api.h::SPOTIFY_API_VERSION\" ref=\"ga63b2309874193750ec3395f6cae32899\" args=\"\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\">#define SPOTIFY_API_VERSION&nbsp;&nbsp;&nbsp;12</td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Current version of the application interface, that is, the API described by this file.</p>\n<p>This value should be set in the <a class=\"el\" href=\"structsp__session__config.html\">sp_session_config</a> struct passed to <a class=\"el\" href=\"group__session.html#gaf2891f2daced4ff6da84219d6376b3aa\">sp_session_create()</a>.</p>\n<p>If an (upgraded) library is no longer compatible with this version the error <a class=\"el\" href=\"group__error.html#ggafd27986ce4cd9eeaeca8adda83c9eb6ba17c588fa9648e3649185e595bdb88d6f\" title=\"The library version targeted does not match the one you claim you support.\">SP_ERROR_BAD_API_VERSION</a> will be returned from <a class=\"el\" href=\"group__session.html#gaf2891f2daced4ff6da84219d6376b3aa\">sp_session_create()</a>. Future versions of the library will provide you with some kind of mechanism to request an updated version of the library. </p>\n\n</div>\n</div>\n<hr/><h2>Typedef Documentation</h2>\n<a class=\"anchor\" id=\"gab947eba77c176504c69cbb2f1de9830d\"></a><!-- doxytag: member=\"api.h::sp_artistbrowse_type\" ref=\"gab947eba77c176504c69cbb2f1de9830d\" args=\"\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\">typedef enum <a class=\"el\" href=\"group__session.html#gac86504cc9e8cadbc30c8aa8dbf355034\">sp_artistbrowse_type</a>  <a class=\"el\" href=\"group__session.html#gac86504cc9e8cadbc30c8aa8dbf355034\">sp_artistbrowse_type</a></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Controls the type of data that will be included in artist browse queries </p>\n\n</div>\n</div>\n<a class=\"anchor\" id=\"ga25462859a596a247ba5cc1853fc32cca\"></a><!-- doxytag: member=\"api.h::sp_audio_buffer_stats\" ref=\"ga25462859a596a247ba5cc1853fc32cca\" args=\"\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\">typedef struct <a class=\"el\" href=\"structsp__audio__buffer__stats.html\">sp_audio_buffer_stats</a>  <a class=\"el\" href=\"structsp__audio__buffer__stats.html\">sp_audio_buffer_stats</a></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Buffer stats used by get_audio_buffer_stats callback </p>\n\n</div>\n</div>\n<a class=\"anchor\" id=\"ga5338d4a10576ba8d6ab11b70892d503c\"></a><!-- doxytag: member=\"api.h::sp_audioformat\" ref=\"ga5338d4a10576ba8d6ab11b70892d503c\" args=\"\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\">typedef struct <a class=\"el\" href=\"structsp__audioformat.html\">sp_audioformat</a>  <a class=\"el\" href=\"structsp__audioformat.html\">sp_audioformat</a></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Audio format descriptor </p>\n\n</div>\n</div>\n<a class=\"anchor\" id=\"ga83d3de45241a44e787410993c5fac0ea\"></a><!-- doxytag: member=\"api.h::sp_bitrate\" ref=\"ga83d3de45241a44e787410993c5fac0ea\" args=\"\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\">typedef enum <a class=\"el\" href=\"group__session.html#ga77ddd919314a7bb16140569af7a38fe2\">sp_bitrate</a>  <a class=\"el\" href=\"group__session.html#ga77ddd919314a7bb16140569af7a38fe2\">sp_bitrate</a></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Bitrate definitions for music streaming </p>\n\n</div>\n</div>\n<a class=\"anchor\" id=\"ga24ee483cdceef9af3b415c020b197a75\"></a><!-- doxytag: member=\"api.h::sp_connection_rules\" ref=\"ga24ee483cdceef9af3b415c020b197a75\" args=\"\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\">typedef enum <a class=\"el\" href=\"group__session.html#gad275d696685b2ad9ff1a2c3e16af6502\">sp_connection_rules</a>  <a class=\"el\" href=\"group__session.html#gad275d696685b2ad9ff1a2c3e16af6502\">sp_connection_rules</a></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Connection rules, bitwise OR of flags</p>\n<p>The default is SP_CONNECTION_RULE_NETWORK | SP_CONNECTION_RULE_ALLOW_SYNC </p>\n\n</div>\n</div>\n<a class=\"anchor\" id=\"ga05a7dbb946a9c47bf011f3f3d77964c3\"></a><!-- doxytag: member=\"api.h::sp_connection_type\" ref=\"ga05a7dbb946a9c47bf011f3f3d77964c3\" args=\"\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\">typedef enum <a class=\"el\" href=\"group__session.html#ga3e8773baeb94189b9a1ff27d6a5e3553\">sp_connection_type</a>  <a class=\"el\" href=\"group__session.html#ga3e8773baeb94189b9a1ff27d6a5e3553\">sp_connection_type</a></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Current connection type set using <a class=\"el\" href=\"group__session.html#gaf81c61799e0ccdbba048fb79ec050930\">sp_session_set_connection_type()</a> </p>\n\n</div>\n</div>\n<a class=\"anchor\" id=\"gac0fa3d4cc60bd2e3d666026f88980e8c\"></a><!-- doxytag: member=\"api.h::sp_connectionstate\" ref=\"gac0fa3d4cc60bd2e3d666026f88980e8c\" args=\"\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\">typedef enum <a class=\"el\" href=\"group__session.html#gabf77bb5a124d5a6ee9a12c86abbc0d34\">sp_connectionstate</a>  <a class=\"el\" href=\"group__session.html#gabf77bb5a124d5a6ee9a12c86abbc0d34\">sp_connectionstate</a></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Describes the current state of the connection </p>\n\n</div>\n</div>\n<a class=\"anchor\" id=\"gaca320fd41bd0556b7fa1f2fa6e14faee\"></a><!-- doxytag: member=\"api.h::sp_image_size\" ref=\"gaca320fd41bd0556b7fa1f2fa6e14faee\" args=\"\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\">typedef enum <a class=\"el\" href=\"group__session.html#ga61bc424465d776af3ceeb69eee2bb492\">sp_image_size</a>  <a class=\"el\" href=\"group__session.html#ga61bc424465d776af3ceeb69eee2bb492\">sp_image_size</a></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Image size </p>\n\n</div>\n</div>\n<a class=\"anchor\" id=\"gaa7f24f13d6d105869c405045a4cc2a20\"></a><!-- doxytag: member=\"api.h::sp_offline_sync_status\" ref=\"gaa7f24f13d6d105869c405045a4cc2a20\" args=\"\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\">typedef struct <a class=\"el\" href=\"structsp__offline__sync__status.html\">sp_offline_sync_status</a>  <a class=\"el\" href=\"structsp__offline__sync__status.html\">sp_offline_sync_status</a></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Offline sync status </p>\n\n</div>\n</div>\n<a class=\"anchor\" id=\"gac507efa32e8c122fbe9ea41d96180d06\"></a><!-- doxytag: member=\"api.h::sp_playlist_offline_status\" ref=\"gac507efa32e8c122fbe9ea41d96180d06\" args=\"\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\">typedef enum <a class=\"el\" href=\"group__session.html#ga811fa52ed0fdb5cda732682e27e40417\">sp_playlist_offline_status</a>  <a class=\"el\" href=\"group__session.html#ga811fa52ed0fdb5cda732682e27e40417\">sp_playlist_offline_status</a></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Playlist offline status </p>\n\n</div>\n</div>\n<a class=\"anchor\" id=\"ga86723f553db2db6a8f507cd748948ad4\"></a><!-- doxytag: member=\"api.h::sp_playlist_type\" ref=\"ga86723f553db2db6a8f507cd748948ad4\" args=\"\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\">typedef enum <a class=\"el\" href=\"group__session.html#gafdd7117213605e6f2671c4f289b44609\">sp_playlist_type</a>  <a class=\"el\" href=\"group__session.html#gafdd7117213605e6f2671c4f289b44609\">sp_playlist_type</a></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Playlist types </p>\n\n</div>\n</div>\n<a class=\"anchor\" id=\"ga5ef462e78d5a5af60dd0e7085b1ba512\"></a><!-- doxytag: member=\"api.h::sp_sampletype\" ref=\"ga5ef462e78d5a5af60dd0e7085b1ba512\" args=\"\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\">typedef enum <a class=\"el\" href=\"group__session.html#ga087d21080010768316cfb55d938eb94d\">sp_sampletype</a>  <a class=\"el\" href=\"group__session.html#ga087d21080010768316cfb55d938eb94d\">sp_sampletype</a></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Sample type descriptor </p>\n\n</div>\n</div>\n<a class=\"anchor\" id=\"ga647e4de81e5ac0a2e5d1193b1005ed3e\"></a><!-- doxytag: member=\"api.h::sp_search_type\" ref=\"ga647e4de81e5ac0a2e5d1193b1005ed3e\" args=\"\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\">typedef enum <a class=\"el\" href=\"group__session.html#ga99e8e9176ce40fff08a9be8b944edb09\">sp_search_type</a>  <a class=\"el\" href=\"group__session.html#ga99e8e9176ce40fff08a9be8b944edb09\">sp_search_type</a></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Search types </p>\n\n</div>\n</div>\n<a class=\"anchor\" id=\"gaf1d92302cd5d0d4a032e1408188c8fd5\"></a><!-- doxytag: member=\"api.h::sp_session_callbacks\" ref=\"gaf1d92302cd5d0d4a032e1408188c8fd5\" args=\"\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\">typedef struct <a class=\"el\" href=\"structsp__session__callbacks.html\">sp_session_callbacks</a>  <a class=\"el\" href=\"structsp__session__callbacks.html\">sp_session_callbacks</a></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Session callbacks</p>\n<p>Registered when you create a session. If some callbacks should not be of interest, set them to NULL. </p>\n\n</div>\n</div>\n<a class=\"anchor\" id=\"ga372b25a93da38d4d707b0c2eaa7b3ebb\"></a><!-- doxytag: member=\"api.h::sp_session_config\" ref=\"ga372b25a93da38d4d707b0c2eaa7b3ebb\" args=\"\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\">typedef struct <a class=\"el\" href=\"structsp__session__config.html\">sp_session_config</a>  <a class=\"el\" href=\"structsp__session__config.html\">sp_session_config</a></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Session config </p>\n\n</div>\n</div>\n<a class=\"anchor\" id=\"gafb515e30d134c61b8eaaff3177af0b5b\"></a><!-- doxytag: member=\"api.h::sp_subscribers\" ref=\"gafb515e30d134c61b8eaaff3177af0b5b\" args=\"\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\">typedef struct <a class=\"el\" href=\"structsp__subscribers.html\">sp_subscribers</a>  <a class=\"el\" href=\"structsp__subscribers.html\">sp_subscribers</a></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>List of subscribers returned by <a class=\"el\" href=\"group__playlist.html#gad49f491babc475f8d4aeea1b4452ff8b\">sp_playlist_subscribers()</a> </p>\n\n</div>\n</div>\n<a class=\"anchor\" id=\"ga60c7ff53ddbc04c036a23181b7275d69\"></a><!-- doxytag: member=\"api.h::sp_track_availability\" ref=\"ga60c7ff53ddbc04c036a23181b7275d69\" args=\"\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\">typedef enum <a class=\"el\" href=\"group__session.html#gad7d9465769597b2a379ac704099adfdf\">sp_availability</a>  <a class=\"el\" href=\"group__session.html#ga60c7ff53ddbc04c036a23181b7275d69\">sp_track_availability</a></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Track availability </p>\n\n</div>\n</div>\n<a class=\"anchor\" id=\"gae689044941537050de641a1dcd4c75d5\"></a><!-- doxytag: member=\"api.h::sp_track_offline_status\" ref=\"gae689044941537050de641a1dcd4c75d5\" args=\"\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\">typedef enum <a class=\"el\" href=\"group__session.html#gaeaa41aad3c0047409996a6ec3b03203f\">sp_track_offline_status</a>  <a class=\"el\" href=\"group__session.html#gaeaa41aad3c0047409996a6ec3b03203f\">sp_track_offline_status</a></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Track offline status </p>\n\n</div>\n</div>\n<hr/><h2>Enumeration Type Documentation</h2>\n<a class=\"anchor\" id=\"gac86504cc9e8cadbc30c8aa8dbf355034\"></a><!-- doxytag: member=\"api.h::sp_artistbrowse_type\" ref=\"gac86504cc9e8cadbc30c8aa8dbf355034\" args=\"\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\">enum <a class=\"el\" href=\"group__session.html#gac86504cc9e8cadbc30c8aa8dbf355034\">sp_artistbrowse_type</a></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Controls the type of data that will be included in artist browse queries </p>\n<dl><dt><b>Enumerator: </b></dt><dd><table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n<tr><td valign=\"top\"><em><a class=\"anchor\" id=\"ggac86504cc9e8cadbc30c8aa8dbf355034a2914168528aded818177c013a0dd7e87\"></a><!-- doxytag: member=\"SP_ARTISTBROWSE_FULL\" ref=\"ggac86504cc9e8cadbc30c8aa8dbf355034a2914168528aded818177c013a0dd7e87\" args=\"\" -->SP_ARTISTBROWSE_FULL</em>&nbsp;</td><td>\n<p>All information except tophit tracks This mode is deprecated and will removed in a future release </p>\n</td></tr>\n<tr><td valign=\"top\"><em><a class=\"anchor\" id=\"ggac86504cc9e8cadbc30c8aa8dbf355034afbad1e58606b3230dce5bc3320c95d12\"></a><!-- doxytag: member=\"SP_ARTISTBROWSE_NO_TRACKS\" ref=\"ggac86504cc9e8cadbc30c8aa8dbf355034afbad1e58606b3230dce5bc3320c95d12\" args=\"\" -->SP_ARTISTBROWSE_NO_TRACKS</em>&nbsp;</td><td>\n<p>Only albums and data about them, no tracks. In other words, <a class=\"el\" href=\"group__artistbrowse.html#ga8c862caa2234125ffcc4e93287b1e029\">sp_artistbrowse_num_tracks()</a> will return 0 </p>\n</td></tr>\n<tr><td valign=\"top\"><em><a class=\"anchor\" id=\"ggac86504cc9e8cadbc30c8aa8dbf355034ac0032981f8dbf44c022e6a7ab1672167\"></a><!-- doxytag: member=\"SP_ARTISTBROWSE_NO_ALBUMS\" ref=\"ggac86504cc9e8cadbc30c8aa8dbf355034ac0032981f8dbf44c022e6a7ab1672167\" args=\"\" -->SP_ARTISTBROWSE_NO_ALBUMS</em>&nbsp;</td><td>\n<p>Only return data about the artist (artist name, similar artist biography, etc No tracks or album will be abailable. <a class=\"el\" href=\"group__artistbrowse.html#ga8c862caa2234125ffcc4e93287b1e029\">sp_artistbrowse_num_tracks()</a> and <a class=\"el\" href=\"group__artistbrowse.html#gaf0055361abd53425d89a4636a32b5c83\">sp_artistbrowse_num_albums()</a> will both return 0 </p>\n</td></tr>\n</table>\n</dd>\n</dl>\n\n</div>\n</div>\n<a class=\"anchor\" id=\"gad7d9465769597b2a379ac704099adfdf\"></a><!-- doxytag: member=\"api.h::sp_availability\" ref=\"gad7d9465769597b2a379ac704099adfdf\" args=\"\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\">enum <a class=\"el\" href=\"group__session.html#gad7d9465769597b2a379ac704099adfdf\">sp_availability</a></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Track availability </p>\n<dl><dt><b>Enumerator: </b></dt><dd><table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n<tr><td valign=\"top\"><em><a class=\"anchor\" id=\"ggad7d9465769597b2a379ac704099adfdfa44bc1e6f138910b3f8dbd309325e0077\"></a><!-- doxytag: member=\"SP_TRACK_AVAILABILITY_UNAVAILABLE\" ref=\"ggad7d9465769597b2a379ac704099adfdfa44bc1e6f138910b3f8dbd309325e0077\" args=\"\" -->SP_TRACK_AVAILABILITY_UNAVAILABLE</em>&nbsp;</td><td>\n<p>Track is not available. </p>\n</td></tr>\n<tr><td valign=\"top\"><em><a class=\"anchor\" id=\"ggad7d9465769597b2a379ac704099adfdfa3b837ba6d740b5650b0113734a3b2ff7\"></a><!-- doxytag: member=\"SP_TRACK_AVAILABILITY_AVAILABLE\" ref=\"ggad7d9465769597b2a379ac704099adfdfa3b837ba6d740b5650b0113734a3b2ff7\" args=\"\" -->SP_TRACK_AVAILABILITY_AVAILABLE</em>&nbsp;</td><td>\n<p>Track is available and can be played. </p>\n</td></tr>\n<tr><td valign=\"top\"><em><a class=\"anchor\" id=\"ggad7d9465769597b2a379ac704099adfdfae7b2cfafa10288ecc50df97621bbe940\"></a><!-- doxytag: member=\"SP_TRACK_AVAILABILITY_NOT_STREAMABLE\" ref=\"ggad7d9465769597b2a379ac704099adfdfae7b2cfafa10288ecc50df97621bbe940\" args=\"\" -->SP_TRACK_AVAILABILITY_NOT_STREAMABLE</em>&nbsp;</td><td>\n<p>Track can not be streamed using this account. </p>\n</td></tr>\n<tr><td valign=\"top\"><em><a class=\"anchor\" id=\"ggad7d9465769597b2a379ac704099adfdfaeb5d63e89c543f513cd3054969e50914\"></a><!-- doxytag: member=\"SP_TRACK_AVAILABILITY_BANNED_BY_ARTIST\" ref=\"ggad7d9465769597b2a379ac704099adfdfaeb5d63e89c543f513cd3054969e50914\" args=\"\" -->SP_TRACK_AVAILABILITY_BANNED_BY_ARTIST</em>&nbsp;</td><td>\n<p>Track not available on artist's reqeust. </p>\n</td></tr>\n</table>\n</dd>\n</dl>\n\n</div>\n</div>\n<a class=\"anchor\" id=\"ga77ddd919314a7bb16140569af7a38fe2\"></a><!-- doxytag: member=\"api.h::sp_bitrate\" ref=\"ga77ddd919314a7bb16140569af7a38fe2\" args=\"\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\">enum <a class=\"el\" href=\"group__session.html#ga77ddd919314a7bb16140569af7a38fe2\">sp_bitrate</a></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Bitrate definitions for music streaming </p>\n<dl><dt><b>Enumerator: </b></dt><dd><table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n<tr><td valign=\"top\"><em><a class=\"anchor\" id=\"gga77ddd919314a7bb16140569af7a38fe2a5b5c794224972f833a4b7eec9d7909c9\"></a><!-- doxytag: member=\"SP_BITRATE_160k\" ref=\"gga77ddd919314a7bb16140569af7a38fe2a5b5c794224972f833a4b7eec9d7909c9\" args=\"\" -->SP_BITRATE_160k</em>&nbsp;</td><td>\n<p>Bitrate 160kbps. </p>\n</td></tr>\n<tr><td valign=\"top\"><em><a class=\"anchor\" id=\"gga77ddd919314a7bb16140569af7a38fe2a9383c0dc9faefd2cbb38c3b9342c47e0\"></a><!-- doxytag: member=\"SP_BITRATE_320k\" ref=\"gga77ddd919314a7bb16140569af7a38fe2a9383c0dc9faefd2cbb38c3b9342c47e0\" args=\"\" -->SP_BITRATE_320k</em>&nbsp;</td><td>\n<p>Bitrate 320kbps. </p>\n</td></tr>\n<tr><td valign=\"top\"><em><a class=\"anchor\" id=\"gga77ddd919314a7bb16140569af7a38fe2ad815a35af7e6bb5e2ef29418af62759b\"></a><!-- doxytag: member=\"SP_BITRATE_96k\" ref=\"gga77ddd919314a7bb16140569af7a38fe2ad815a35af7e6bb5e2ef29418af62759b\" args=\"\" -->SP_BITRATE_96k</em>&nbsp;</td><td>\n<p>Bitrate 96kbps. </p>\n</td></tr>\n</table>\n</dd>\n</dl>\n\n</div>\n</div>\n<a class=\"anchor\" id=\"gad275d696685b2ad9ff1a2c3e16af6502\"></a><!-- doxytag: member=\"api.h::sp_connection_rules\" ref=\"gad275d696685b2ad9ff1a2c3e16af6502\" args=\"\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\">enum <a class=\"el\" href=\"group__session.html#gad275d696685b2ad9ff1a2c3e16af6502\">sp_connection_rules</a></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Connection rules, bitwise OR of flags</p>\n<p>The default is SP_CONNECTION_RULE_NETWORK | SP_CONNECTION_RULE_ALLOW_SYNC </p>\n<dl><dt><b>Enumerator: </b></dt><dd><table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n<tr><td valign=\"top\"><em><a class=\"anchor\" id=\"ggad275d696685b2ad9ff1a2c3e16af6502aa39a1c21c17c55cd1547bc900ae2d386\"></a><!-- doxytag: member=\"SP_CONNECTION_RULE_NETWORK\" ref=\"ggad275d696685b2ad9ff1a2c3e16af6502aa39a1c21c17c55cd1547bc900ae2d386\" args=\"\" -->SP_CONNECTION_RULE_NETWORK</em>&nbsp;</td><td>\n<p>Allow network traffic. When not set libspotify will force itself into offline mode. </p>\n</td></tr>\n<tr><td valign=\"top\"><em><a class=\"anchor\" id=\"ggad275d696685b2ad9ff1a2c3e16af6502af2772ba84ee7e410ad99708a11955670\"></a><!-- doxytag: member=\"SP_CONNECTION_RULE_NETWORK_IF_ROAMING\" ref=\"ggad275d696685b2ad9ff1a2c3e16af6502af2772ba84ee7e410ad99708a11955670\" args=\"\" -->SP_CONNECTION_RULE_NETWORK_IF_ROAMING</em>&nbsp;</td><td>\n<p>Allow network traffic even if roaming. </p>\n</td></tr>\n<tr><td valign=\"top\"><em><a class=\"anchor\" id=\"ggad275d696685b2ad9ff1a2c3e16af6502a91a946573c44de44d74e9d20dbce4c74\"></a><!-- doxytag: member=\"SP_CONNECTION_RULE_ALLOW_SYNC_OVER_MOBILE\" ref=\"ggad275d696685b2ad9ff1a2c3e16af6502a91a946573c44de44d74e9d20dbce4c74\" args=\"\" -->SP_CONNECTION_RULE_ALLOW_SYNC_OVER_MOBILE</em>&nbsp;</td><td>\n<p>Set to allow syncing of offline content over mobile connections. </p>\n</td></tr>\n<tr><td valign=\"top\"><em><a class=\"anchor\" id=\"ggad275d696685b2ad9ff1a2c3e16af6502a548f3734832ec65a992e598d8b91633d\"></a><!-- doxytag: member=\"SP_CONNECTION_RULE_ALLOW_SYNC_OVER_WIFI\" ref=\"ggad275d696685b2ad9ff1a2c3e16af6502a548f3734832ec65a992e598d8b91633d\" args=\"\" -->SP_CONNECTION_RULE_ALLOW_SYNC_OVER_WIFI</em>&nbsp;</td><td>\n<p>Set to allow syncing of offline content over WiFi. </p>\n</td></tr>\n</table>\n</dd>\n</dl>\n\n</div>\n</div>\n<a class=\"anchor\" id=\"ga3e8773baeb94189b9a1ff27d6a5e3553\"></a><!-- doxytag: member=\"api.h::sp_connection_type\" ref=\"ga3e8773baeb94189b9a1ff27d6a5e3553\" args=\"\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\">enum <a class=\"el\" href=\"group__session.html#ga3e8773baeb94189b9a1ff27d6a5e3553\">sp_connection_type</a></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Current connection type set using <a class=\"el\" href=\"group__session.html#gaf81c61799e0ccdbba048fb79ec050930\">sp_session_set_connection_type()</a> </p>\n<dl><dt><b>Enumerator: </b></dt><dd><table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n<tr><td valign=\"top\"><em><a class=\"anchor\" id=\"gga3e8773baeb94189b9a1ff27d6a5e3553af949fae9bc12f47b99ef290fa9b5d8a7\"></a><!-- doxytag: member=\"SP_CONNECTION_TYPE_UNKNOWN\" ref=\"gga3e8773baeb94189b9a1ff27d6a5e3553af949fae9bc12f47b99ef290fa9b5d8a7\" args=\"\" -->SP_CONNECTION_TYPE_UNKNOWN</em>&nbsp;</td><td>\n<p>Connection type unknown (Default). </p>\n</td></tr>\n<tr><td valign=\"top\"><em><a class=\"anchor\" id=\"gga3e8773baeb94189b9a1ff27d6a5e3553aa7aae7ae3f7c471ece1c6aa2705d046c\"></a><!-- doxytag: member=\"SP_CONNECTION_TYPE_NONE\" ref=\"gga3e8773baeb94189b9a1ff27d6a5e3553aa7aae7ae3f7c471ece1c6aa2705d046c\" args=\"\" -->SP_CONNECTION_TYPE_NONE</em>&nbsp;</td><td>\n<p>No connection. </p>\n</td></tr>\n<tr><td valign=\"top\"><em><a class=\"anchor\" id=\"gga3e8773baeb94189b9a1ff27d6a5e3553a3ca3e6a85ac9d497914c35620ad5179d\"></a><!-- doxytag: member=\"SP_CONNECTION_TYPE_MOBILE\" ref=\"gga3e8773baeb94189b9a1ff27d6a5e3553a3ca3e6a85ac9d497914c35620ad5179d\" args=\"\" -->SP_CONNECTION_TYPE_MOBILE</em>&nbsp;</td><td>\n<p>Mobile data (EDGE, 3G, etc). </p>\n</td></tr>\n<tr><td valign=\"top\"><em><a class=\"anchor\" id=\"gga3e8773baeb94189b9a1ff27d6a5e3553a05b41bbfd369f9030a7daafc9395116e\"></a><!-- doxytag: member=\"SP_CONNECTION_TYPE_MOBILE_ROAMING\" ref=\"gga3e8773baeb94189b9a1ff27d6a5e3553a05b41bbfd369f9030a7daafc9395116e\" args=\"\" -->SP_CONNECTION_TYPE_MOBILE_ROAMING</em>&nbsp;</td><td>\n<p>Roamed mobile data (EDGE, 3G, etc). </p>\n</td></tr>\n<tr><td valign=\"top\"><em><a class=\"anchor\" id=\"gga3e8773baeb94189b9a1ff27d6a5e3553a31d2cad7379f1bc2eeedd24c40541cb9\"></a><!-- doxytag: member=\"SP_CONNECTION_TYPE_WIFI\" ref=\"gga3e8773baeb94189b9a1ff27d6a5e3553a31d2cad7379f1bc2eeedd24c40541cb9\" args=\"\" -->SP_CONNECTION_TYPE_WIFI</em>&nbsp;</td><td>\n<p>Wireless connection. </p>\n</td></tr>\n<tr><td valign=\"top\"><em><a class=\"anchor\" id=\"gga3e8773baeb94189b9a1ff27d6a5e3553a4f9f0c09e59af4114bb369ebcc474710\"></a><!-- doxytag: member=\"SP_CONNECTION_TYPE_WIRED\" ref=\"gga3e8773baeb94189b9a1ff27d6a5e3553a4f9f0c09e59af4114bb369ebcc474710\" args=\"\" -->SP_CONNECTION_TYPE_WIRED</em>&nbsp;</td><td>\n<p>Ethernet cable, etc. </p>\n</td></tr>\n</table>\n</dd>\n</dl>\n\n</div>\n</div>\n<a class=\"anchor\" id=\"gabf77bb5a124d5a6ee9a12c86abbc0d34\"></a><!-- doxytag: member=\"api.h::sp_connectionstate\" ref=\"gabf77bb5a124d5a6ee9a12c86abbc0d34\" args=\"\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\">enum <a class=\"el\" href=\"group__session.html#gabf77bb5a124d5a6ee9a12c86abbc0d34\">sp_connectionstate</a></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Describes the current state of the connection </p>\n<dl><dt><b>Enumerator: </b></dt><dd><table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n<tr><td valign=\"top\"><em><a class=\"anchor\" id=\"ggabf77bb5a124d5a6ee9a12c86abbc0d34ae31e9958a98211ecff5ecbcf7041dfa5\"></a><!-- doxytag: member=\"SP_CONNECTION_STATE_LOGGED_OUT\" ref=\"ggabf77bb5a124d5a6ee9a12c86abbc0d34ae31e9958a98211ecff5ecbcf7041dfa5\" args=\"\" -->SP_CONNECTION_STATE_LOGGED_OUT</em>&nbsp;</td><td>\n<p>User not yet logged in. </p>\n</td></tr>\n<tr><td valign=\"top\"><em><a class=\"anchor\" id=\"ggabf77bb5a124d5a6ee9a12c86abbc0d34a88ae17b4168184e62e4c190c289c47c5\"></a><!-- doxytag: member=\"SP_CONNECTION_STATE_LOGGED_IN\" ref=\"ggabf77bb5a124d5a6ee9a12c86abbc0d34a88ae17b4168184e62e4c190c289c47c5\" args=\"\" -->SP_CONNECTION_STATE_LOGGED_IN</em>&nbsp;</td><td>\n<p>Logged in against a Spotify access point. </p>\n</td></tr>\n<tr><td valign=\"top\"><em><a class=\"anchor\" id=\"ggabf77bb5a124d5a6ee9a12c86abbc0d34ad1a6eb721675af4613f823c091538a8c\"></a><!-- doxytag: member=\"SP_CONNECTION_STATE_DISCONNECTED\" ref=\"ggabf77bb5a124d5a6ee9a12c86abbc0d34ad1a6eb721675af4613f823c091538a8c\" args=\"\" -->SP_CONNECTION_STATE_DISCONNECTED</em>&nbsp;</td><td>\n<p>Was logged in, but has now been disconnected. </p>\n</td></tr>\n<tr><td valign=\"top\"><em><a class=\"anchor\" id=\"ggabf77bb5a124d5a6ee9a12c86abbc0d34a4ddf57518007eef86b06f496d7059484\"></a><!-- doxytag: member=\"SP_CONNECTION_STATE_UNDEFINED\" ref=\"ggabf77bb5a124d5a6ee9a12c86abbc0d34a4ddf57518007eef86b06f496d7059484\" args=\"\" -->SP_CONNECTION_STATE_UNDEFINED</em>&nbsp;</td><td>\n<p>The connection state is undefined. </p>\n</td></tr>\n<tr><td valign=\"top\"><em><a class=\"anchor\" id=\"ggabf77bb5a124d5a6ee9a12c86abbc0d34a63099ef9185ba287fcd2e77be3c47d8f\"></a><!-- doxytag: member=\"SP_CONNECTION_STATE_OFFLINE\" ref=\"ggabf77bb5a124d5a6ee9a12c86abbc0d34a63099ef9185ba287fcd2e77be3c47d8f\" args=\"\" -->SP_CONNECTION_STATE_OFFLINE</em>&nbsp;</td><td>\n<p>Logged in in offline mode. </p>\n</td></tr>\n</table>\n</dd>\n</dl>\n\n</div>\n</div>\n<a class=\"anchor\" id=\"ga61bc424465d776af3ceeb69eee2bb492\"></a><!-- doxytag: member=\"api.h::sp_image_size\" ref=\"ga61bc424465d776af3ceeb69eee2bb492\" args=\"\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\">enum <a class=\"el\" href=\"group__session.html#ga61bc424465d776af3ceeb69eee2bb492\">sp_image_size</a></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Image size </p>\n<dl><dt><b>Enumerator: </b></dt><dd><table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n<tr><td valign=\"top\"><em><a class=\"anchor\" id=\"gga61bc424465d776af3ceeb69eee2bb492ad20c808fd1f8180d1f49f643975d1dd7\"></a><!-- doxytag: member=\"SP_IMAGE_SIZE_NORMAL\" ref=\"gga61bc424465d776af3ceeb69eee2bb492ad20c808fd1f8180d1f49f643975d1dd7\" args=\"\" -->SP_IMAGE_SIZE_NORMAL</em>&nbsp;</td><td>\n<p>Normal image size. </p>\n</td></tr>\n<tr><td valign=\"top\"><em><a class=\"anchor\" id=\"gga61bc424465d776af3ceeb69eee2bb492ab9340b1bcf2129c3ad1328ea617d547f\"></a><!-- doxytag: member=\"SP_IMAGE_SIZE_SMALL\" ref=\"gga61bc424465d776af3ceeb69eee2bb492ab9340b1bcf2129c3ad1328ea617d547f\" args=\"\" -->SP_IMAGE_SIZE_SMALL</em>&nbsp;</td><td>\n<p>Small image size. </p>\n</td></tr>\n<tr><td valign=\"top\"><em><a class=\"anchor\" id=\"gga61bc424465d776af3ceeb69eee2bb492a0a0b624afbb2a66ee3d7954202b89721\"></a><!-- doxytag: member=\"SP_IMAGE_SIZE_LARGE\" ref=\"gga61bc424465d776af3ceeb69eee2bb492a0a0b624afbb2a66ee3d7954202b89721\" args=\"\" -->SP_IMAGE_SIZE_LARGE</em>&nbsp;</td><td>\n<p>Large image size. </p>\n</td></tr>\n</table>\n</dd>\n</dl>\n\n</div>\n</div>\n<a class=\"anchor\" id=\"ga811fa52ed0fdb5cda732682e27e40417\"></a><!-- doxytag: member=\"api.h::sp_playlist_offline_status\" ref=\"ga811fa52ed0fdb5cda732682e27e40417\" args=\"\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\">enum <a class=\"el\" href=\"group__session.html#ga811fa52ed0fdb5cda732682e27e40417\">sp_playlist_offline_status</a></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Playlist offline status </p>\n<dl><dt><b>Enumerator: </b></dt><dd><table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n<tr><td valign=\"top\"><em><a class=\"anchor\" id=\"gga811fa52ed0fdb5cda732682e27e40417abef62e4e3a4af8827fed7fe3aa733ca0\"></a><!-- doxytag: member=\"SP_PLAYLIST_OFFLINE_STATUS_NO\" ref=\"gga811fa52ed0fdb5cda732682e27e40417abef62e4e3a4af8827fed7fe3aa733ca0\" args=\"\" -->SP_PLAYLIST_OFFLINE_STATUS_NO</em>&nbsp;</td><td>\n<p>Playlist is not offline enabled. </p>\n</td></tr>\n<tr><td valign=\"top\"><em><a class=\"anchor\" id=\"gga811fa52ed0fdb5cda732682e27e40417affed38ac820e084b96fb48e3d1939584\"></a><!-- doxytag: member=\"SP_PLAYLIST_OFFLINE_STATUS_YES\" ref=\"gga811fa52ed0fdb5cda732682e27e40417affed38ac820e084b96fb48e3d1939584\" args=\"\" -->SP_PLAYLIST_OFFLINE_STATUS_YES</em>&nbsp;</td><td>\n<p>Playlist is synchronized to local storage. </p>\n</td></tr>\n<tr><td valign=\"top\"><em><a class=\"anchor\" id=\"gga811fa52ed0fdb5cda732682e27e40417abc999c70761d392b26753708e9a2cfa1\"></a><!-- doxytag: member=\"SP_PLAYLIST_OFFLINE_STATUS_DOWNLOADING\" ref=\"gga811fa52ed0fdb5cda732682e27e40417abc999c70761d392b26753708e9a2cfa1\" args=\"\" -->SP_PLAYLIST_OFFLINE_STATUS_DOWNLOADING</em>&nbsp;</td><td>\n<p>This playlist is currently downloading. Only one playlist can be in this state any given time. </p>\n</td></tr>\n<tr><td valign=\"top\"><em><a class=\"anchor\" id=\"gga811fa52ed0fdb5cda732682e27e40417a7d929bbf4f1df3633b283e39b9c95919\"></a><!-- doxytag: member=\"SP_PLAYLIST_OFFLINE_STATUS_WAITING\" ref=\"gga811fa52ed0fdb5cda732682e27e40417a7d929bbf4f1df3633b283e39b9c95919\" args=\"\" -->SP_PLAYLIST_OFFLINE_STATUS_WAITING</em>&nbsp;</td><td>\n<p>Playlist is queued for download. </p>\n</td></tr>\n</table>\n</dd>\n</dl>\n\n</div>\n</div>\n<a class=\"anchor\" id=\"gafdd7117213605e6f2671c4f289b44609\"></a><!-- doxytag: member=\"api.h::sp_playlist_type\" ref=\"gafdd7117213605e6f2671c4f289b44609\" args=\"\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\">enum <a class=\"el\" href=\"group__session.html#gafdd7117213605e6f2671c4f289b44609\">sp_playlist_type</a></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Playlist types </p>\n<dl><dt><b>Enumerator: </b></dt><dd><table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n<tr><td valign=\"top\"><em><a class=\"anchor\" id=\"ggafdd7117213605e6f2671c4f289b44609a6bd6bf9b62018fa9bbf969835c2f3077\"></a><!-- doxytag: member=\"SP_PLAYLIST_TYPE_PLAYLIST\" ref=\"ggafdd7117213605e6f2671c4f289b44609a6bd6bf9b62018fa9bbf969835c2f3077\" args=\"\" -->SP_PLAYLIST_TYPE_PLAYLIST</em>&nbsp;</td><td>\n<p>A normal playlist. </p>\n</td></tr>\n<tr><td valign=\"top\"><em><a class=\"anchor\" id=\"ggafdd7117213605e6f2671c4f289b44609a4d3266991787f9438deb9de83d9200da\"></a><!-- doxytag: member=\"SP_PLAYLIST_TYPE_START_FOLDER\" ref=\"ggafdd7117213605e6f2671c4f289b44609a4d3266991787f9438deb9de83d9200da\" args=\"\" -->SP_PLAYLIST_TYPE_START_FOLDER</em>&nbsp;</td><td>\n<p>Marks a folder starting point,. </p>\n</td></tr>\n<tr><td valign=\"top\"><em><a class=\"anchor\" id=\"ggafdd7117213605e6f2671c4f289b44609a3ec52ad1d99d8e32e1b9de31e3f5187a\"></a><!-- doxytag: member=\"SP_PLAYLIST_TYPE_END_FOLDER\" ref=\"ggafdd7117213605e6f2671c4f289b44609a3ec52ad1d99d8e32e1b9de31e3f5187a\" args=\"\" -->SP_PLAYLIST_TYPE_END_FOLDER</em>&nbsp;</td><td>\n<p>and ending point. </p>\n</td></tr>\n<tr><td valign=\"top\"><em><a class=\"anchor\" id=\"ggafdd7117213605e6f2671c4f289b44609ad4f860ef76154e3e2c0d9da2f57a2784\"></a><!-- doxytag: member=\"SP_PLAYLIST_TYPE_PLACEHOLDER\" ref=\"ggafdd7117213605e6f2671c4f289b44609ad4f860ef76154e3e2c0d9da2f57a2784\" args=\"\" -->SP_PLAYLIST_TYPE_PLACEHOLDER</em>&nbsp;</td><td>\n<p>Unknown entry. </p>\n</td></tr>\n</table>\n</dd>\n</dl>\n\n</div>\n</div>\n<a class=\"anchor\" id=\"ga087d21080010768316cfb55d938eb94d\"></a><!-- doxytag: member=\"api.h::sp_sampletype\" ref=\"ga087d21080010768316cfb55d938eb94d\" args=\"\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\">enum <a class=\"el\" href=\"group__session.html#ga087d21080010768316cfb55d938eb94d\">sp_sampletype</a></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Sample type descriptor </p>\n<dl><dt><b>Enumerator: </b></dt><dd><table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n<tr><td valign=\"top\"><em><a class=\"anchor\" id=\"gga087d21080010768316cfb55d938eb94daa829b269d191cca95ecb02c2bc59da42\"></a><!-- doxytag: member=\"SP_SAMPLETYPE_INT16_NATIVE_ENDIAN\" ref=\"gga087d21080010768316cfb55d938eb94daa829b269d191cca95ecb02c2bc59da42\" args=\"\" -->SP_SAMPLETYPE_INT16_NATIVE_ENDIAN</em>&nbsp;</td><td>\n<p>16-bit signed integer samples </p>\n</td></tr>\n</table>\n</dd>\n</dl>\n\n</div>\n</div>\n<a class=\"anchor\" id=\"ga99e8e9176ce40fff08a9be8b944edb09\"></a><!-- doxytag: member=\"api.h::sp_search_type\" ref=\"ga99e8e9176ce40fff08a9be8b944edb09\" args=\"\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\">enum <a class=\"el\" href=\"group__session.html#ga99e8e9176ce40fff08a9be8b944edb09\">sp_search_type</a></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Search types </p>\n\n</div>\n</div>\n<a class=\"anchor\" id=\"gaeaa41aad3c0047409996a6ec3b03203f\"></a><!-- doxytag: member=\"api.h::sp_track_offline_status\" ref=\"gaeaa41aad3c0047409996a6ec3b03203f\" args=\"\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\">enum <a class=\"el\" href=\"group__session.html#gaeaa41aad3c0047409996a6ec3b03203f\">sp_track_offline_status</a></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Track offline status </p>\n<dl><dt><b>Enumerator: </b></dt><dd><table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n<tr><td valign=\"top\"><em><a class=\"anchor\" id=\"ggaeaa41aad3c0047409996a6ec3b03203faad1a1cba82ce9f9be678f4d1042eddec\"></a><!-- doxytag: member=\"SP_TRACK_OFFLINE_NO\" ref=\"ggaeaa41aad3c0047409996a6ec3b03203faad1a1cba82ce9f9be678f4d1042eddec\" args=\"\" -->SP_TRACK_OFFLINE_NO</em>&nbsp;</td><td>\n<p>Not marked for offline. </p>\n</td></tr>\n<tr><td valign=\"top\"><em><a class=\"anchor\" id=\"ggaeaa41aad3c0047409996a6ec3b03203fa1fdd2a518dcdc072cfca27a0ca4f2581\"></a><!-- doxytag: member=\"SP_TRACK_OFFLINE_WAITING\" ref=\"ggaeaa41aad3c0047409996a6ec3b03203fa1fdd2a518dcdc072cfca27a0ca4f2581\" args=\"\" -->SP_TRACK_OFFLINE_WAITING</em>&nbsp;</td><td>\n<p>Waiting for download. </p>\n</td></tr>\n<tr><td valign=\"top\"><em><a class=\"anchor\" id=\"ggaeaa41aad3c0047409996a6ec3b03203fa7dcf6dfc56a8421200451d07a476f370\"></a><!-- doxytag: member=\"SP_TRACK_OFFLINE_DOWNLOADING\" ref=\"ggaeaa41aad3c0047409996a6ec3b03203fa7dcf6dfc56a8421200451d07a476f370\" args=\"\" -->SP_TRACK_OFFLINE_DOWNLOADING</em>&nbsp;</td><td>\n<p>Currently downloading. </p>\n</td></tr>\n<tr><td valign=\"top\"><em><a class=\"anchor\" id=\"ggaeaa41aad3c0047409996a6ec3b03203fac54d46cbc73de7686a1ad8daf269532a\"></a><!-- doxytag: member=\"SP_TRACK_OFFLINE_DONE\" ref=\"ggaeaa41aad3c0047409996a6ec3b03203fac54d46cbc73de7686a1ad8daf269532a\" args=\"\" -->SP_TRACK_OFFLINE_DONE</em>&nbsp;</td><td>\n<p>Downloaded OK and can be played. </p>\n</td></tr>\n<tr><td valign=\"top\"><em><a class=\"anchor\" id=\"ggaeaa41aad3c0047409996a6ec3b03203fa86618798c266540bdc889dd037a52631\"></a><!-- doxytag: member=\"SP_TRACK_OFFLINE_ERROR\" ref=\"ggaeaa41aad3c0047409996a6ec3b03203fa86618798c266540bdc889dd037a52631\" args=\"\" -->SP_TRACK_OFFLINE_ERROR</em>&nbsp;</td><td>\n<p>Error during download. </p>\n</td></tr>\n<tr><td valign=\"top\"><em><a class=\"anchor\" id=\"ggaeaa41aad3c0047409996a6ec3b03203fa00fe430030fb6a8a49a46c11cca7326c\"></a><!-- doxytag: member=\"SP_TRACK_OFFLINE_DONE_EXPIRED\" ref=\"ggaeaa41aad3c0047409996a6ec3b03203fa00fe430030fb6a8a49a46c11cca7326c\" args=\"\" -->SP_TRACK_OFFLINE_DONE_EXPIRED</em>&nbsp;</td><td>\n<p>Downloaded OK but not playable due to expiery. </p>\n</td></tr>\n<tr><td valign=\"top\"><em><a class=\"anchor\" id=\"ggaeaa41aad3c0047409996a6ec3b03203fa405a9b7a3fa489ad2dadbb108794e247\"></a><!-- doxytag: member=\"SP_TRACK_OFFLINE_LIMIT_EXCEEDED\" ref=\"ggaeaa41aad3c0047409996a6ec3b03203fa405a9b7a3fa489ad2dadbb108794e247\" args=\"\" -->SP_TRACK_OFFLINE_LIMIT_EXCEEDED</em>&nbsp;</td><td>\n<p>Waiting because device have reached max number of allowed tracks. </p>\n</td></tr>\n<tr><td valign=\"top\"><em><a class=\"anchor\" id=\"ggaeaa41aad3c0047409996a6ec3b03203fa5f3e19627de4509ae4a3864fd29edee6\"></a><!-- doxytag: member=\"SP_TRACK_OFFLINE_DONE_RESYNC\" ref=\"ggaeaa41aad3c0047409996a6ec3b03203fa5f3e19627de4509ae4a3864fd29edee6\" args=\"\" -->SP_TRACK_OFFLINE_DONE_RESYNC</em>&nbsp;</td><td>\n<p>Downloaded OK and available but scheduled for re-download. </p>\n</td></tr>\n</table>\n</dd>\n</dl>\n\n</div>\n</div>\n<hr/><h2>Function Documentation</h2>\n<a class=\"anchor\" id=\"gad6cee58fa44453b7a4fd2ae2266df055\"></a><!-- doxytag: member=\"api.h::sp_offline_num_playlists\" ref=\"gad6cee58fa44453b7a4fd2ae2266df055\" args=\"(sp_session *session)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\">int sp_offline_num_playlists </td>\n          <td>(</td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__types.html#ga70dd19c6f824cf6a159575aa4c128b53\">sp_session</a> *&nbsp;</td>\n          <td class=\"paramname\"> <em>session</em></td>\n          <td>&nbsp;)&nbsp;</td>\n          <td></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Return number of playlisys that is marked for offline synchronization</p>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>session</em>&nbsp;</td><td>Session object</td></tr>\n  </table>\n  </dd>\n</dl>\n<dl class=\"return\"><dt><b>Returns:</b></dt><dd>Number of playlists </dd></dl>\n\n</div>\n</div>\n<a class=\"anchor\" id=\"ga02525cd659a34728047cd3801049e822\"></a><!-- doxytag: member=\"api.h::sp_offline_sync_get_status\" ref=\"ga02525cd659a34728047cd3801049e822\" args=\"(sp_session *session, sp_offline_sync_status *status)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\">bool sp_offline_sync_get_status </td>\n          <td>(</td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__types.html#ga70dd19c6f824cf6a159575aa4c128b53\">sp_session</a> *&nbsp;</td>\n          <td class=\"paramname\"> <em>session</em>, </td>\n        </tr>\n        <tr>\n          <td class=\"paramkey\"></td>\n          <td></td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"structsp__offline__sync__status.html\">sp_offline_sync_status</a> *&nbsp;</td>\n          <td class=\"paramname\"> <em>status</em></td><td>&nbsp;</td>\n        </tr>\n        <tr>\n          <td></td>\n          <td>)</td>\n          <td></td><td></td><td></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Return offline synchronization status. When the internal status is updated the offline_status_updated() callback will be invoked.</p>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>session</em>&nbsp;</td><td>Session object </td></tr>\n    <tr><td valign=\"top\"><tt>[out]</tt>&nbsp;</td><td valign=\"top\"><em>status</em>&nbsp;</td><td>Status object that will be filled with info</td></tr>\n  </table>\n  </dd>\n</dl>\n<dl class=\"return\"><dt><b>Returns:</b></dt><dd>false if no synching is in progress (in which case the contents of status is undefined) </dd></dl>\n\n</div>\n</div>\n<a class=\"anchor\" id=\"gac36816dc42825db9a5a2fbd2694f20af\"></a><!-- doxytag: member=\"api.h::sp_offline_time_left\" ref=\"gac36816dc42825db9a5a2fbd2694f20af\" args=\"(sp_session *session)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\">int sp_offline_time_left </td>\n          <td>(</td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__types.html#ga70dd19c6f824cf6a159575aa4c128b53\">sp_session</a> *&nbsp;</td>\n          <td class=\"paramname\"> <em>session</em></td>\n          <td>&nbsp;)&nbsp;</td>\n          <td></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Return remaining time (in seconds) until the offline key store expires and the user is required to relogin</p>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>session</em>&nbsp;</td><td>Session object </td></tr>\n  </table>\n  </dd>\n</dl>\n<dl class=\"return\"><dt><b>Returns:</b></dt><dd>Seconds until expiration </dd></dl>\n\n</div>\n</div>\n<a class=\"anchor\" id=\"gaf535124b4208c279cb98a061834e6411\"></a><!-- doxytag: member=\"api.h::sp_offline_tracks_to_sync\" ref=\"gaf535124b4208c279cb98a061834e6411\" args=\"(sp_session *session)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\">int sp_offline_tracks_to_sync </td>\n          <td>(</td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__types.html#ga70dd19c6f824cf6a159575aa4c128b53\">sp_session</a> *&nbsp;</td>\n          <td class=\"paramname\"> <em>session</em></td>\n          <td>&nbsp;)&nbsp;</td>\n          <td></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Get total number of tracks that needs download before everything from all playlists that is marked for offline is fully synchronized</p>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>session</em>&nbsp;</td><td>Session object</td></tr>\n  </table>\n  </dd>\n</dl>\n<dl class=\"return\"><dt><b>Returns:</b></dt><dd>Number of tracks </dd></dl>\n\n</div>\n</div>\n<a class=\"anchor\" id=\"ga34a7c9527705ab7d23b742006d81ea35\"></a><!-- doxytag: member=\"api.h::sp_session_connectionstate\" ref=\"ga34a7c9527705ab7d23b742006d81ea35\" args=\"(sp_session *session)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\"><a class=\"el\" href=\"group__session.html#gabf77bb5a124d5a6ee9a12c86abbc0d34\">sp_connectionstate</a> sp_session_connectionstate </td>\n          <td>(</td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__types.html#ga70dd19c6f824cf6a159575aa4c128b53\">sp_session</a> *&nbsp;</td>\n          <td class=\"paramname\"> <em>session</em></td>\n          <td>&nbsp;)&nbsp;</td>\n          <td></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>The connection state of the specified session.</p>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>session</em>&nbsp;</td><td>Your session object</td></tr>\n  </table>\n  </dd>\n</dl>\n<dl class=\"return\"><dt><b>Returns:</b></dt><dd>The connection state - see the sp_connectionstate enum for possible values </dd></dl>\n\n</div>\n</div>\n<a class=\"anchor\" id=\"gaf2891f2daced4ff6da84219d6376b3aa\"></a><!-- doxytag: member=\"api.h::sp_session_create\" ref=\"gaf2891f2daced4ff6da84219d6376b3aa\" args=\"(const sp_session_config *config, sp_session **sess)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\"><a class=\"el\" href=\"group__error.html#gafd27986ce4cd9eeaeca8adda83c9eb6b\">sp_error</a> sp_session_create </td>\n          <td>(</td>\n          <td class=\"paramtype\">const <a class=\"el\" href=\"structsp__session__config.html\">sp_session_config</a> *&nbsp;</td>\n          <td class=\"paramname\"> <em>config</em>, </td>\n        </tr>\n        <tr>\n          <td class=\"paramkey\"></td>\n          <td></td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__types.html#ga70dd19c6f824cf6a159575aa4c128b53\">sp_session</a> **&nbsp;</td>\n          <td class=\"paramname\"> <em>sess</em></td><td>&nbsp;</td>\n        </tr>\n        <tr>\n          <td></td>\n          <td>)</td>\n          <td></td><td></td><td></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Initialize a session. The session returned will be initialized, but you will need to log in before you can perform any other operation Currently it is not supported to have multiple active sessions, and it's recommended to only call this once per process.</p>\n<p>Here is a snippet from <code>spshell.c:</code>  <div class=\"fragment\"><pre class=\"fragment\">    config.api_version = SPOTIFY_API_VERSION;\n\n    <span class=\"comment\">// The path of the directory to store the cache. This must be specified.</span>\n    <span class=\"comment\">// Please read the documentation on preferred values.</span>\n    config.cache_location = selftest ? <span class=\"stringliteral\">&quot;&quot;</span> : <span class=\"stringliteral\">&quot;tmp&quot;</span>;\n\n    <span class=\"comment\">// The path of the directory to store the settings. </span>\n    <span class=\"comment\">// This must be specified.</span>\n    <span class=\"comment\">// Please read the documentation on preferred values.</span>\n    config.settings_location = selftest ? <span class=\"stringliteral\">&quot;&quot;</span> : <span class=\"stringliteral\">&quot;tmp&quot;</span>;\n\n    <span class=\"comment\">// The key of the application. They are generated by Spotify,</span>\n    <span class=\"comment\">// and are specific to each application using libspotify.</span>\n    config.application_key = g_appkey;\n    config.application_key_size = g_appkey_size;\n\n    <span class=\"comment\">// This identifies the application using some</span>\n    <span class=\"comment\">// free-text string [1, 255] characters.</span>\n    config.user_agent = <span class=\"stringliteral\">&quot;spshell&quot;</span>;\n\n<span class=\"comment\">//ifdef SP_WITH_CURL</span>\n<span class=\"preprocessor\">#ifdef SP_WITH_CURL</span>\n<span class=\"preprocessor\"></span>    config.ca_certs_filename = <span class=\"stringliteral\">&quot;../cacerts.pem&quot;</span>;\n<span class=\"preprocessor\">#endif</span>\n<span class=\"preprocessor\"></span><span class=\"comment\">//endif</span>\n\n    <span class=\"comment\">// Register the callbacks.</span>\n    callbacks.logged_in = logged_in;\n    callbacks.logged_out = logged_out;\n    callbacks.metadata_updated = metadata_updated;\n    callbacks.connection_error = connection_error;\n    callbacks.notify_main_thread = notify_main_thread;\n<span class=\"preprocessor\">#if WITH_TEST_COMMAND</span>\n<span class=\"preprocessor\"></span>    callbacks.music_delivery = music_delivery;\n    callbacks.play_token_lost = play_token_lost;\n    callbacks.end_of_track = end_of_track;\n<span class=\"preprocessor\">#endif</span>\n<span class=\"preprocessor\"></span>    callbacks.log_message = log_message;\n    callbacks.offline_status_updated = offline_status_updated;\n    callbacks.credentials_blob_updated = credentials_blob_updated;\n<span class=\"comment\">//ifdef SP_LIBSPOTIFY_WITH_SCROBBLING</span>\n<span class=\"preprocessor\">#ifdef SP_LIBSPOTIFY_WITH_SCROBBLING</span>\n<span class=\"preprocessor\"></span>    callbacks.scrobble_error = scrobble_error;\n    callbacks.private_session_mode_changed = private_session_mode_changed;\n<span class=\"preprocessor\">#endif</span>\n<span class=\"preprocessor\"></span><span class=\"comment\">//endif</span>\n    config.callbacks = &amp;callbacks;\n\n    error = <a class=\"code\" href=\"group__session.html#gaf2891f2daced4ff6da84219d6376b3aa\">sp_session_create</a>(&amp;config, &amp;session);\n    <span class=\"keywordflow\">if</span> (<a class=\"code\" href=\"group__error.html#ggafd27986ce4cd9eeaeca8adda83c9eb6ba16cb277dc84328e4b2c0cf6d5a0c0b8d\" title=\"No errors encountered.\">SP_ERROR_OK</a> != error) {\n        fprintf(stderr, <span class=\"stringliteral\">&quot;failed to create session: %s\\n&quot;</span>,\n                        <a class=\"code\" href=\"group__error.html#ga983dee341d3c2008830513b7cffe7bf3\">sp_error_message</a>(error));\n        <span class=\"keywordflow\">return</span> 2;\n    }\n</pre></div></p>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>config</em>&nbsp;</td><td>The configuration to use for the session </td></tr>\n    <tr><td valign=\"top\"><tt>[out]</tt>&nbsp;</td><td valign=\"top\"><em>sess</em>&nbsp;</td><td>If successful, a new session - otherwise NULL</td></tr>\n  </table>\n  </dd>\n</dl>\n<dl class=\"return\"><dt><b>Returns:</b></dt><dd>One of the following errors, from <a class=\"el\" href=\"group__error.html#ga83154178d3a32668658734d2facfa22b\">sp_error</a> SP_ERROR_OK SP_ERROR_BAD_API_VERSION SP_ERROR_BAD_USER_AGENT SP_ERROR_BAD_APPLICATION_KEY SP_ERROR_API_INITIALIZATION_FAILED SP_ERROR_INVALID_DEVICE_ID </dd></dl>\n<dl><dt><b>Examples: </b></dt><dd><a class=\"el\" href=\"jukebox_8c-example.html#a25\">jukebox.c</a>.</dd>\n</dl>\n</div>\n</div>\n<a class=\"anchor\" id=\"ga34005bb06ee3de8ee4221597a0335cca\"></a><!-- doxytag: member=\"api.h::sp_session_flush_caches\" ref=\"ga34005bb06ee3de8ee4221597a0335cca\" args=\"(sp_session *session)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\"><a class=\"el\" href=\"group__error.html#gafd27986ce4cd9eeaeca8adda83c9eb6b\">sp_error</a> sp_session_flush_caches </td>\n          <td>(</td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__types.html#ga70dd19c6f824cf6a159575aa4c128b53\">sp_session</a> *&nbsp;</td>\n          <td class=\"paramname\"> <em>session</em></td>\n          <td>&nbsp;)&nbsp;</td>\n          <td></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Flush the caches</p>\n<p>This will make libspotify write all data that is meant to be stored on disk to the disk immediately. libspotify does this periodically by itself and also on logout. So under normal conditions this should never need to be used.</p>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>session</em>&nbsp;</td><td>Your session object </td></tr>\n  </table>\n  </dd>\n</dl>\n<dl class=\"return\"><dt><b>Returns:</b></dt><dd>One of the following errors, from <a class=\"el\" href=\"group__error.html#ga83154178d3a32668658734d2facfa22b\">sp_error</a> SP_ERROR_OK </dd></dl>\n\n</div>\n</div>\n<a class=\"anchor\" id=\"ga61e6b796d9e07682c018e888b901a191\"></a><!-- doxytag: member=\"api.h::sp_session_forget_me\" ref=\"ga61e6b796d9e07682c018e888b901a191\" args=\"(sp_session *session)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\"><a class=\"el\" href=\"group__error.html#gafd27986ce4cd9eeaeca8adda83c9eb6b\">sp_error</a> sp_session_forget_me </td>\n          <td>(</td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__types.html#ga70dd19c6f824cf6a159575aa4c128b53\">sp_session</a> *&nbsp;</td>\n          <td class=\"paramname\"> <em>session</em></td>\n          <td>&nbsp;)&nbsp;</td>\n          <td></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Remove stored credentials in libspotify. If no credentials are currently stored, nothing will happen.</p>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>session</em>&nbsp;</td><td>Your session object </td></tr>\n  </table>\n  </dd>\n</dl>\n<dl class=\"return\"><dt><b>Returns:</b></dt><dd>One of the following errors, from <a class=\"el\" href=\"group__error.html#ga83154178d3a32668658734d2facfa22b\">sp_error</a> SP_ERROR_OK </dd></dl>\n\n</div>\n</div>\n<a class=\"anchor\" id=\"ga7913df06394360f255c77fb87af0f1fe\"></a><!-- doxytag: member=\"api.h::sp_session_get_volume_normalization\" ref=\"ga7913df06394360f255c77fb87af0f1fe\" args=\"(sp_session *session)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\">bool sp_session_get_volume_normalization </td>\n          <td>(</td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__types.html#ga70dd19c6f824cf6a159575aa4c128b53\">sp_session</a> *&nbsp;</td>\n          <td class=\"paramname\"> <em>session</em></td>\n          <td>&nbsp;)&nbsp;</td>\n          <td></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Return status of volume normalization</p>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>session</em>&nbsp;</td><td>Session object</td></tr>\n  </table>\n  </dd>\n</dl>\n<dl class=\"return\"><dt><b>Returns:</b></dt><dd>true iff volume normalization is enabled </dd></dl>\n\n</div>\n</div>\n<a class=\"anchor\" id=\"gac72ccb51031c846101134b73195bb9ec\"></a><!-- doxytag: member=\"api.h::sp_session_inbox_create\" ref=\"gac72ccb51031c846101134b73195bb9ec\" args=\"(sp_session *session)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\"><a class=\"el\" href=\"group__types.html#ga1bcf54cbc117a20ab2c15e59eb3a8174\">sp_playlist</a>* sp_session_inbox_create </td>\n          <td>(</td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__types.html#ga70dd19c6f824cf6a159575aa4c128b53\">sp_session</a> *&nbsp;</td>\n          <td class=\"paramname\"> <em>session</em></td>\n          <td>&nbsp;)&nbsp;</td>\n          <td></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Returns an inbox playlist for the currently logged in user</p>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>session</em>&nbsp;</td><td>Session object</td></tr>\n  </table>\n  </dd>\n</dl>\n<dl class=\"return\"><dt><b>Returns:</b></dt><dd>A playlist or NULL if no user is logged in </dd></dl>\n<dl class=\"note\"><dt><b>Note:</b></dt><dd>You need to release the playlist when you are done with it. </dd></dl>\n<dl class=\"see\"><dt><b>See also:</b></dt><dd><a class=\"el\" href=\"group__playlist.html#gacb9250eb530869b039541a8b62dfab6c\">sp_playlist_release()</a> </dd></dl>\n\n</div>\n</div>\n<a class=\"anchor\" id=\"ga72702ee06bc96c074804388d24344149\"></a><!-- doxytag: member=\"api.h::sp_session_is_private_session\" ref=\"ga72702ee06bc96c074804388d24344149\" args=\"(sp_session *session)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\">bool sp_session_is_private_session </td>\n          <td>(</td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__types.html#ga70dd19c6f824cf6a159575aa4c128b53\">sp_session</a> *&nbsp;</td>\n          <td class=\"paramname\"> <em>session</em></td>\n          <td>&nbsp;)&nbsp;</td>\n          <td></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Return True if private session is enabled</p>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>session</em>&nbsp;</td><td>Session object</td></tr>\n  </table>\n  </dd>\n</dl>\n<dl class=\"return\"><dt><b>Returns:</b></dt><dd>True if private session is enabled </dd></dl>\n\n</div>\n</div>\n<a class=\"anchor\" id=\"ga6a56bc82ff0b369bb6e0f035534ce33d\"></a><!-- doxytag: member=\"api.h::sp_session_is_scrobbling\" ref=\"ga6a56bc82ff0b369bb6e0f035534ce33d\" args=\"(sp_session *session, sp_social_provider provider, sp_scrobbling_state *state)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\"><a class=\"el\" href=\"group__error.html#gafd27986ce4cd9eeaeca8adda83c9eb6b\">sp_error</a> sp_session_is_scrobbling </td>\n          <td>(</td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__types.html#ga70dd19c6f824cf6a159575aa4c128b53\">sp_session</a> *&nbsp;</td>\n          <td class=\"paramname\"> <em>session</em>, </td>\n        </tr>\n        <tr>\n          <td class=\"paramkey\"></td>\n          <td></td>\n          <td class=\"paramtype\">sp_social_provider&nbsp;</td>\n          <td class=\"paramname\"> <em>provider</em>, </td>\n        </tr>\n        <tr>\n          <td class=\"paramkey\"></td>\n          <td></td>\n          <td class=\"paramtype\">sp_scrobbling_state *&nbsp;</td>\n          <td class=\"paramname\"> <em>state</em></td><td>&nbsp;</td>\n        </tr>\n        <tr>\n          <td></td>\n          <td>)</td>\n          <td></td><td></td><td></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Return the scrobbling state. This makes it possible to find out if scrobbling is locally overrided or if the global setting is used.</p>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>session</em>&nbsp;</td><td>Session object </td></tr>\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>provider</em>&nbsp;</td><td>The scrobbling provider referred to </td></tr>\n    <tr><td valign=\"top\"><tt>[out]</tt>&nbsp;</td><td valign=\"top\"><em>state</em>&nbsp;</td><td>The output variable receiving the sp_scrobbling_state state</td></tr>\n  </table>\n  </dd>\n</dl>\n<dl class=\"return\"><dt><b>Returns:</b></dt><dd>error code </dd></dl>\n\n</div>\n</div>\n<a class=\"anchor\" id=\"ga0fad03ceabcf8d68af78f0f35fcbcc8d\"></a><!-- doxytag: member=\"api.h::sp_session_is_scrobbling_possible\" ref=\"ga0fad03ceabcf8d68af78f0f35fcbcc8d\" args=\"(sp_session *session, sp_social_provider provider, bool *out)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\"><a class=\"el\" href=\"group__error.html#gafd27986ce4cd9eeaeca8adda83c9eb6b\">sp_error</a> sp_session_is_scrobbling_possible </td>\n          <td>(</td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__types.html#ga70dd19c6f824cf6a159575aa4c128b53\">sp_session</a> *&nbsp;</td>\n          <td class=\"paramname\"> <em>session</em>, </td>\n        </tr>\n        <tr>\n          <td class=\"paramkey\"></td>\n          <td></td>\n          <td class=\"paramtype\">sp_social_provider&nbsp;</td>\n          <td class=\"paramname\"> <em>provider</em>, </td>\n        </tr>\n        <tr>\n          <td class=\"paramkey\"></td>\n          <td></td>\n          <td class=\"paramtype\">bool *&nbsp;</td>\n          <td class=\"paramname\"> <em>out</em></td><td>&nbsp;</td>\n        </tr>\n        <tr>\n          <td></td>\n          <td>)</td>\n          <td></td><td></td><td></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Return True if scrobbling settings should be shown to the user. Currently this setting is relevant only to the facebook provider. The returned value may be false if the user is not connected to facebook, or if the user has opted out from facebook social graph.</p>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>session</em>&nbsp;</td><td>Session object </td></tr>\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>provider</em>&nbsp;</td><td>The scrobbling provider referred to </td></tr>\n    <tr><td valign=\"top\"><tt>[out]</tt>&nbsp;</td><td valign=\"top\"><em>out</em>&nbsp;</td><td>True iff scrobbling is possible</td></tr>\n  </table>\n  </dd>\n</dl>\n<dl class=\"return\"><dt><b>Returns:</b></dt><dd>error code </dd></dl>\n\n</div>\n</div>\n<a class=\"anchor\" id=\"ga4533a992a120cacb109c892a852afe2a\"></a><!-- doxytag: member=\"api.h::sp_session_login\" ref=\"ga4533a992a120cacb109c892a852afe2a\" args=\"(sp_session *session, const char *username, const char *password, bool remember_me, const char *blob)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\"><a class=\"el\" href=\"group__error.html#gafd27986ce4cd9eeaeca8adda83c9eb6b\">sp_error</a> sp_session_login </td>\n          <td>(</td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__types.html#ga70dd19c6f824cf6a159575aa4c128b53\">sp_session</a> *&nbsp;</td>\n          <td class=\"paramname\"> <em>session</em>, </td>\n        </tr>\n        <tr>\n          <td class=\"paramkey\"></td>\n          <td></td>\n          <td class=\"paramtype\">const char *&nbsp;</td>\n          <td class=\"paramname\"> <em>username</em>, </td>\n        </tr>\n        <tr>\n          <td class=\"paramkey\"></td>\n          <td></td>\n          <td class=\"paramtype\">const char *&nbsp;</td>\n          <td class=\"paramname\"> <em>password</em>, </td>\n        </tr>\n        <tr>\n          <td class=\"paramkey\"></td>\n          <td></td>\n          <td class=\"paramtype\">bool&nbsp;</td>\n          <td class=\"paramname\"> <em>remember_me</em>, </td>\n        </tr>\n        <tr>\n          <td class=\"paramkey\"></td>\n          <td></td>\n          <td class=\"paramtype\">const char *&nbsp;</td>\n          <td class=\"paramname\"> <em>blob</em></td><td>&nbsp;</td>\n        </tr>\n        <tr>\n          <td></td>\n          <td>)</td>\n          <td></td><td></td><td></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Logs in the specified username/password combo. This initiates the login in the background. A callback is called when login is complete</p>\n<p>An application MUST NEVER store the user's password in clear text. If automatic relogin is required, use <a class=\"el\" href=\"group__session.html#gae1bc9bebd230226c3d48925cd1be6edf\">sp_session_relogin()</a></p>\n<p>Here is a snippet from <code>spshell.c:</code>  <div class=\"fragment\"><pre class=\"fragment\">        <a class=\"code\" href=\"group__session.html#ga4533a992a120cacb109c892a852afe2a\">sp_session_login</a>(session, username, password, 1, blob);\n    }\n</pre></div></p>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>session</em>&nbsp;</td><td>Your session object </td></tr>\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>username</em>&nbsp;</td><td>The username to log in </td></tr>\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>password</em>&nbsp;</td><td>The password for the specified username </td></tr>\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>remember_me</em>&nbsp;</td><td>If set, the username / password will be remembered by libspotify </td></tr>\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>blob</em>&nbsp;</td><td>If you have received a blob in the credentials_blob_updated you can pas this here instead of password </td></tr>\n  </table>\n  </dd>\n</dl>\n<dl class=\"return\"><dt><b>Returns:</b></dt><dd>One of the following errors, from <a class=\"el\" href=\"group__error.html#ga83154178d3a32668658734d2facfa22b\">sp_error</a> SP_ERROR_OK </dd></dl>\n<dl><dt><b>Examples: </b></dt><dd><a class=\"el\" href=\"jukebox_8c-example.html#a26\">jukebox.c</a>.</dd>\n</dl>\n</div>\n</div>\n<a class=\"anchor\" id=\"gab7f08ca0939985b30ae2d1ed9db1d726\"></a><!-- doxytag: member=\"api.h::sp_session_logout\" ref=\"gab7f08ca0939985b30ae2d1ed9db1d726\" args=\"(sp_session *session)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\"><a class=\"el\" href=\"group__error.html#gafd27986ce4cd9eeaeca8adda83c9eb6b\">sp_error</a> sp_session_logout </td>\n          <td>(</td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__types.html#ga70dd19c6f824cf6a159575aa4c128b53\">sp_session</a> *&nbsp;</td>\n          <td class=\"paramname\"> <em>session</em></td>\n          <td>&nbsp;)&nbsp;</td>\n          <td></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Logs out the currently logged in user</p>\n<p>Always call this before terminating the application and libspotify is currently logged in. Otherwise, the settings and cache may be lost.</p>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>session</em>&nbsp;</td><td>Your session object </td></tr>\n  </table>\n  </dd>\n</dl>\n<dl class=\"return\"><dt><b>Returns:</b></dt><dd>One of the following errors, from <a class=\"el\" href=\"group__error.html#ga83154178d3a32668658734d2facfa22b\">sp_error</a> SP_ERROR_OK </dd></dl>\n\n</div>\n</div>\n<a class=\"anchor\" id=\"gac73bf2c569a43d824439b557d5e4b293\"></a><!-- doxytag: member=\"api.h::sp_session_player_load\" ref=\"gac73bf2c569a43d824439b557d5e4b293\" args=\"(sp_session *session, sp_track *track)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\"><a class=\"el\" href=\"group__error.html#gafd27986ce4cd9eeaeca8adda83c9eb6b\">sp_error</a> sp_session_player_load </td>\n          <td>(</td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__types.html#ga70dd19c6f824cf6a159575aa4c128b53\">sp_session</a> *&nbsp;</td>\n          <td class=\"paramname\"> <em>session</em>, </td>\n        </tr>\n        <tr>\n          <td class=\"paramkey\"></td>\n          <td></td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__types.html#ga47bbd2262f0c8b5d7147af7d62198e48\">sp_track</a> *&nbsp;</td>\n          <td class=\"paramname\"> <em>track</em></td><td>&nbsp;</td>\n        </tr>\n        <tr>\n          <td></td>\n          <td>)</td>\n          <td></td><td></td><td></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Loads the specified track</p>\n<p>After successfully loading the track, you have the option of running <a class=\"el\" href=\"group__session.html#gab66c5915967e4f90db945b118e620624\">sp_session_player_play()</a> directly, or using <a class=\"el\" href=\"group__session.html#ga3430cd4f11541868d3f83eaa31aecf44\">sp_session_player_seek()</a> first. When this call returns, the track will have been loaded, unless an error occurred.</p>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>session</em>&nbsp;</td><td>Your session object </td></tr>\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>track</em>&nbsp;</td><td>The track to be loaded</td></tr>\n  </table>\n  </dd>\n</dl>\n<dl class=\"return\"><dt><b>Returns:</b></dt><dd>One of the following errors, from <a class=\"el\" href=\"group__error.html#ga83154178d3a32668658734d2facfa22b\">sp_error</a> SP_ERROR_OK SP_ERROR_MISSING_CALLBACK SP_ERROR_TRACK_NOT_PLAYABLE </dd></dl>\n<dl><dt><b>Examples: </b></dt><dd><a class=\"el\" href=\"jukebox_8c-example.html#a6\">jukebox.c</a>.</dd>\n</dl>\n</div>\n</div>\n<a class=\"anchor\" id=\"gab66c5915967e4f90db945b118e620624\"></a><!-- doxytag: member=\"api.h::sp_session_player_play\" ref=\"gab66c5915967e4f90db945b118e620624\" args=\"(sp_session *session, bool play)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\"><a class=\"el\" href=\"group__error.html#gafd27986ce4cd9eeaeca8adda83c9eb6b\">sp_error</a> sp_session_player_play </td>\n          <td>(</td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__types.html#ga70dd19c6f824cf6a159575aa4c128b53\">sp_session</a> *&nbsp;</td>\n          <td class=\"paramname\"> <em>session</em>, </td>\n        </tr>\n        <tr>\n          <td class=\"paramkey\"></td>\n          <td></td>\n          <td class=\"paramtype\">bool&nbsp;</td>\n          <td class=\"paramname\"> <em>play</em></td><td>&nbsp;</td>\n        </tr>\n        <tr>\n          <td></td>\n          <td>)</td>\n          <td></td><td></td><td></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Play or pause the currently loaded track</p>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>session</em>&nbsp;</td><td>Your session object </td></tr>\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>play</em>&nbsp;</td><td>If set to true, playback will occur. If set to false, the playback will be paused. </td></tr>\n  </table>\n  </dd>\n</dl>\n<dl class=\"return\"><dt><b>Returns:</b></dt><dd>One of the following errors, from <a class=\"el\" href=\"group__error.html#ga83154178d3a32668658734d2facfa22b\">sp_error</a> SP_ERROR_OK </dd></dl>\n<dl><dt><b>Examples: </b></dt><dd><a class=\"el\" href=\"jukebox_8c-example.html#a7\">jukebox.c</a>.</dd>\n</dl>\n</div>\n</div>\n<a class=\"anchor\" id=\"gaf42e30a1f430ac7c436c7d9f0485368d\"></a><!-- doxytag: member=\"api.h::sp_session_player_prefetch\" ref=\"gaf42e30a1f430ac7c436c7d9f0485368d\" args=\"(sp_session *session, sp_track *track)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\"><a class=\"el\" href=\"group__error.html#gafd27986ce4cd9eeaeca8adda83c9eb6b\">sp_error</a> sp_session_player_prefetch </td>\n          <td>(</td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__types.html#ga70dd19c6f824cf6a159575aa4c128b53\">sp_session</a> *&nbsp;</td>\n          <td class=\"paramname\"> <em>session</em>, </td>\n        </tr>\n        <tr>\n          <td class=\"paramkey\"></td>\n          <td></td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__types.html#ga47bbd2262f0c8b5d7147af7d62198e48\">sp_track</a> *&nbsp;</td>\n          <td class=\"paramname\"> <em>track</em></td><td>&nbsp;</td>\n        </tr>\n        <tr>\n          <td></td>\n          <td>)</td>\n          <td></td><td></td><td></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Prefetch a track</p>\n<p>Instruct libspotify to start loading of a track into its cache. This could be done by an application just before the current track ends.</p>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>session</em>&nbsp;</td><td>Your session object </td></tr>\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>track</em>&nbsp;</td><td>The track to be prefetched</td></tr>\n  </table>\n  </dd>\n</dl>\n<dl class=\"return\"><dt><b>Returns:</b></dt><dd>One of the following errors, from <a class=\"el\" href=\"group__error.html#ga83154178d3a32668658734d2facfa22b\">sp_error</a> SP_ERROR_NO_CACHE SP_ERROR_OK</dd></dl>\n<dl class=\"note\"><dt><b>Note:</b></dt><dd>Prefetching is only possible if a cache is configured </dd></dl>\n\n</div>\n</div>\n<a class=\"anchor\" id=\"ga3430cd4f11541868d3f83eaa31aecf44\"></a><!-- doxytag: member=\"api.h::sp_session_player_seek\" ref=\"ga3430cd4f11541868d3f83eaa31aecf44\" args=\"(sp_session *session, int offset)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\"><a class=\"el\" href=\"group__error.html#gafd27986ce4cd9eeaeca8adda83c9eb6b\">sp_error</a> sp_session_player_seek </td>\n          <td>(</td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__types.html#ga70dd19c6f824cf6a159575aa4c128b53\">sp_session</a> *&nbsp;</td>\n          <td class=\"paramname\"> <em>session</em>, </td>\n        </tr>\n        <tr>\n          <td class=\"paramkey\"></td>\n          <td></td>\n          <td class=\"paramtype\">int&nbsp;</td>\n          <td class=\"paramname\"> <em>offset</em></td><td>&nbsp;</td>\n        </tr>\n        <tr>\n          <td></td>\n          <td>)</td>\n          <td></td><td></td><td></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Seek to position in the currently loaded track</p>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>session</em>&nbsp;</td><td>Your session object </td></tr>\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>offset</em>&nbsp;</td><td>Track position, in milliseconds. </td></tr>\n  </table>\n  </dd>\n</dl>\n<dl class=\"return\"><dt><b>Returns:</b></dt><dd>One of the following errors, from <a class=\"el\" href=\"group__error.html#ga83154178d3a32668658734d2facfa22b\">sp_error</a> SP_ERROR_OK </dd></dl>\n\n</div>\n</div>\n<a class=\"anchor\" id=\"gafa7ee2803f119451bb8be3bf28746975\"></a><!-- doxytag: member=\"api.h::sp_session_player_unload\" ref=\"gafa7ee2803f119451bb8be3bf28746975\" args=\"(sp_session *session)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\"><a class=\"el\" href=\"group__error.html#gafd27986ce4cd9eeaeca8adda83c9eb6b\">sp_error</a> sp_session_player_unload </td>\n          <td>(</td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__types.html#ga70dd19c6f824cf6a159575aa4c128b53\">sp_session</a> *&nbsp;</td>\n          <td class=\"paramname\"> <em>session</em></td>\n          <td>&nbsp;)&nbsp;</td>\n          <td></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Stops the currently playing track</p>\n<p>This frees some resources held by libspotify to identify the currently playing track.</p>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>session</em>&nbsp;</td><td>Your session object </td></tr>\n  </table>\n  </dd>\n</dl>\n<dl class=\"return\"><dt><b>Returns:</b></dt><dd>One of the following errors, from <a class=\"el\" href=\"group__error.html#ga83154178d3a32668658734d2facfa22b\">sp_error</a> SP_ERROR_OK </dd></dl>\n<dl><dt><b>Examples: </b></dt><dd><a class=\"el\" href=\"jukebox_8c-example.html#a2\">jukebox.c</a>.</dd>\n</dl>\n</div>\n</div>\n<a class=\"anchor\" id=\"ga319767f0b795f1c46a08390b587c5671\"></a><!-- doxytag: member=\"api.h::sp_session_playlistcontainer\" ref=\"ga319767f0b795f1c46a08390b587c5671\" args=\"(sp_session *session)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\"><a class=\"el\" href=\"group__types.html#ga45a2febbe167483e48dab8d606d462d7\">sp_playlistcontainer</a>* sp_session_playlistcontainer </td>\n          <td>(</td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__types.html#ga70dd19c6f824cf6a159575aa4c128b53\">sp_session</a> *&nbsp;</td>\n          <td class=\"paramname\"> <em>session</em></td>\n          <td>&nbsp;)&nbsp;</td>\n          <td></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Returns the playlist container for the currently logged in user.</p>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>session</em>&nbsp;</td><td>Your session object</td></tr>\n  </table>\n  </dd>\n</dl>\n<dl class=\"return\"><dt><b>Returns:</b></dt><dd>Playlist container object, NULL if not logged in </dd></dl>\n<dl><dt><b>Examples: </b></dt><dd><a class=\"el\" href=\"jukebox_8c-example.html#a14\">jukebox.c</a>.</dd>\n</dl>\n</div>\n</div>\n<a class=\"anchor\" id=\"gacd590e095b011af42fb10046117846fe\"></a><!-- doxytag: member=\"api.h::sp_session_preferred_bitrate\" ref=\"gacd590e095b011af42fb10046117846fe\" args=\"(sp_session *session, sp_bitrate bitrate)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\"><a class=\"el\" href=\"group__error.html#gafd27986ce4cd9eeaeca8adda83c9eb6b\">sp_error</a> sp_session_preferred_bitrate </td>\n          <td>(</td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__types.html#ga70dd19c6f824cf6a159575aa4c128b53\">sp_session</a> *&nbsp;</td>\n          <td class=\"paramname\"> <em>session</em>, </td>\n        </tr>\n        <tr>\n          <td class=\"paramkey\"></td>\n          <td></td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__session.html#ga77ddd919314a7bb16140569af7a38fe2\">sp_bitrate</a>&nbsp;</td>\n          <td class=\"paramname\"> <em>bitrate</em></td><td>&nbsp;</td>\n        </tr>\n        <tr>\n          <td></td>\n          <td>)</td>\n          <td></td><td></td><td></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Set preferred bitrate for music streaming</p>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>session</em>&nbsp;</td><td>Session object </td></tr>\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>bitrate</em>&nbsp;</td><td>Preferred bitrate, see <a class=\"el\" href=\"group__session.html#ga83d3de45241a44e787410993c5fac0ea\">sp_bitrate</a> for possible values </td></tr>\n  </table>\n  </dd>\n</dl>\n<dl class=\"return\"><dt><b>Returns:</b></dt><dd>One of the following errors, from <a class=\"el\" href=\"group__error.html#ga83154178d3a32668658734d2facfa22b\">sp_error</a> SP_ERROR_OK SP_ERROR_INVALID_ARGUMENT </dd></dl>\n\n</div>\n</div>\n<a class=\"anchor\" id=\"ga4bba5f828d6c87692f2c355cc8f07c61\"></a><!-- doxytag: member=\"api.h::sp_session_preferred_offline_bitrate\" ref=\"ga4bba5f828d6c87692f2c355cc8f07c61\" args=\"(sp_session *session, sp_bitrate bitrate, bool allow_resync)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\"><a class=\"el\" href=\"group__error.html#gafd27986ce4cd9eeaeca8adda83c9eb6b\">sp_error</a> sp_session_preferred_offline_bitrate </td>\n          <td>(</td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__types.html#ga70dd19c6f824cf6a159575aa4c128b53\">sp_session</a> *&nbsp;</td>\n          <td class=\"paramname\"> <em>session</em>, </td>\n        </tr>\n        <tr>\n          <td class=\"paramkey\"></td>\n          <td></td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__session.html#ga77ddd919314a7bb16140569af7a38fe2\">sp_bitrate</a>&nbsp;</td>\n          <td class=\"paramname\"> <em>bitrate</em>, </td>\n        </tr>\n        <tr>\n          <td class=\"paramkey\"></td>\n          <td></td>\n          <td class=\"paramtype\">bool&nbsp;</td>\n          <td class=\"paramname\"> <em>allow_resync</em></td><td>&nbsp;</td>\n        </tr>\n        <tr>\n          <td></td>\n          <td>)</td>\n          <td></td><td></td><td></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Set preferred bitrate for offline sync</p>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>session</em>&nbsp;</td><td>Session object </td></tr>\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>bitrate</em>&nbsp;</td><td>Preferred bitrate, see <a class=\"el\" href=\"group__session.html#ga83d3de45241a44e787410993c5fac0ea\">sp_bitrate</a> for possible values </td></tr>\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>allow_resync</em>&nbsp;</td><td>Set to true if libspotify should resynchronize already synchronized tracks. Usually you should set this to false. </td></tr>\n  </table>\n  </dd>\n</dl>\n<dl class=\"return\"><dt><b>Returns:</b></dt><dd>One of the following errors, from <a class=\"el\" href=\"group__error.html#ga83154178d3a32668658734d2facfa22b\">sp_error</a> SP_ERROR_OK SP_ERROR_INVALID_ARGUMENT </dd></dl>\n\n</div>\n</div>\n<a class=\"anchor\" id=\"gaff27cb730db6debf55e750e39e7fadd7\"></a><!-- doxytag: member=\"api.h::sp_session_process_events\" ref=\"gaff27cb730db6debf55e750e39e7fadd7\" args=\"(sp_session *session, int *next_timeout)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\"><a class=\"el\" href=\"group__error.html#gafd27986ce4cd9eeaeca8adda83c9eb6b\">sp_error</a> sp_session_process_events </td>\n          <td>(</td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__types.html#ga70dd19c6f824cf6a159575aa4c128b53\">sp_session</a> *&nbsp;</td>\n          <td class=\"paramname\"> <em>session</em>, </td>\n        </tr>\n        <tr>\n          <td class=\"paramkey\"></td>\n          <td></td>\n          <td class=\"paramtype\">int *&nbsp;</td>\n          <td class=\"paramname\"> <em>next_timeout</em></td><td>&nbsp;</td>\n        </tr>\n        <tr>\n          <td></td>\n          <td>)</td>\n          <td></td><td></td><td></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Make the specified session process any pending events</p>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>session</em>&nbsp;</td><td>Your session object </td></tr>\n    <tr><td valign=\"top\"><tt>[out]</tt>&nbsp;</td><td valign=\"top\"><em>next_timeout</em>&nbsp;</td><td>Stores the time (in milliseconds) until you should call this function again </td></tr>\n  </table>\n  </dd>\n</dl>\n<dl class=\"return\"><dt><b>Returns:</b></dt><dd>One of the following errors, from <a class=\"el\" href=\"group__error.html#ga83154178d3a32668658734d2facfa22b\">sp_error</a> SP_ERROR_OK </dd></dl>\n<dl><dt><b>Examples: </b></dt><dd><a class=\"el\" href=\"jukebox_8c-example.html#a27\">jukebox.c</a>.</dd>\n</dl>\n</div>\n</div>\n<a class=\"anchor\" id=\"ga4ad3a1de596a41f275120dad3bb4685d\"></a><!-- doxytag: member=\"api.h::sp_session_publishedcontainer_for_user_create\" ref=\"ga4ad3a1de596a41f275120dad3bb4685d\" args=\"(sp_session *session, const char *canonical_username)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\"><a class=\"el\" href=\"group__types.html#ga45a2febbe167483e48dab8d606d462d7\">sp_playlistcontainer</a>* sp_session_publishedcontainer_for_user_create </td>\n          <td>(</td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__types.html#ga70dd19c6f824cf6a159575aa4c128b53\">sp_session</a> *&nbsp;</td>\n          <td class=\"paramname\"> <em>session</em>, </td>\n        </tr>\n        <tr>\n          <td class=\"paramkey\"></td>\n          <td></td>\n          <td class=\"paramtype\">const char *&nbsp;</td>\n          <td class=\"paramname\"> <em>canonical_username</em></td><td>&nbsp;</td>\n        </tr>\n        <tr>\n          <td></td>\n          <td>)</td>\n          <td></td><td></td><td></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Return the published container for a given <em>canonical_username</em>, or the currently logged in user if <em>canonical_username</em> is NULL.</p>\n<p>When done with the list you should call sp_playlistconatiner_release() to decrese the reference you own by having created it.</p>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>session</em>&nbsp;</td><td>Your session object. </td></tr>\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>canonical_username</em>&nbsp;</td><td>The canonical username, or NULL.</td></tr>\n  </table>\n  </dd>\n</dl>\n<dl class=\"return\"><dt><b>Returns:</b></dt><dd>Playlist container object, NULL if not logged in. </dd></dl>\n\n</div>\n</div>\n<a class=\"anchor\" id=\"gab81c540b76f7425a9cc0dbf270c09674\"></a><!-- doxytag: member=\"api.h::sp_session_release\" ref=\"gab81c540b76f7425a9cc0dbf270c09674\" args=\"(sp_session *sess)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\"><a class=\"el\" href=\"group__error.html#gafd27986ce4cd9eeaeca8adda83c9eb6b\">sp_error</a> sp_session_release </td>\n          <td>(</td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__types.html#ga70dd19c6f824cf6a159575aa4c128b53\">sp_session</a> *&nbsp;</td>\n          <td class=\"paramname\"> <em>sess</em></td>\n          <td>&nbsp;)&nbsp;</td>\n          <td></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Release the session. This will clean up all data and connections associated with the session</p>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>sess</em>&nbsp;</td><td>Session object returned from <a class=\"el\" href=\"group__session.html#gaf2891f2daced4ff6da84219d6376b3aa\">sp_session_create()</a> </td></tr>\n  </table>\n  </dd>\n</dl>\n<dl class=\"return\"><dt><b>Returns:</b></dt><dd>One of the following errors, from <a class=\"el\" href=\"group__error.html#ga83154178d3a32668658734d2facfa22b\">sp_error</a> SP_ERROR_OK </dd></dl>\n\n</div>\n</div>\n<a class=\"anchor\" id=\"gae1bc9bebd230226c3d48925cd1be6edf\"></a><!-- doxytag: member=\"api.h::sp_session_relogin\" ref=\"gae1bc9bebd230226c3d48925cd1be6edf\" args=\"(sp_session *session)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\"><a class=\"el\" href=\"group__error.html#gafd27986ce4cd9eeaeca8adda83c9eb6b\">sp_error</a> sp_session_relogin </td>\n          <td>(</td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__types.html#ga70dd19c6f824cf6a159575aa4c128b53\">sp_session</a> *&nbsp;</td>\n          <td class=\"paramname\"> <em>session</em></td>\n          <td>&nbsp;)&nbsp;</td>\n          <td></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Log in the remembered user if last user that logged in logged in with remember_me set. If no credentials are stored, this will return SP_ERROR_NO_CREDENTIALS.</p>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>session</em>&nbsp;</td><td>Your session object</td></tr>\n  </table>\n  </dd>\n</dl>\n<dl class=\"return\"><dt><b>Returns:</b></dt><dd>One of the following errors, from <a class=\"el\" href=\"group__error.html#ga83154178d3a32668658734d2facfa22b\">sp_error</a> SP_ERROR_OK SP_ERROR_NO_CREDENTIALS </dd></dl>\n\n</div>\n</div>\n<a class=\"anchor\" id=\"gab349c7bfe59e10e167bd75c20df9fc97\"></a><!-- doxytag: member=\"api.h::sp_session_remembered_user\" ref=\"gab349c7bfe59e10e167bd75c20df9fc97\" args=\"(sp_session *session, char *buffer, size_t buffer_size)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\">int sp_session_remembered_user </td>\n          <td>(</td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__types.html#ga70dd19c6f824cf6a159575aa4c128b53\">sp_session</a> *&nbsp;</td>\n          <td class=\"paramname\"> <em>session</em>, </td>\n        </tr>\n        <tr>\n          <td class=\"paramkey\"></td>\n          <td></td>\n          <td class=\"paramtype\">char *&nbsp;</td>\n          <td class=\"paramname\"> <em>buffer</em>, </td>\n        </tr>\n        <tr>\n          <td class=\"paramkey\"></td>\n          <td></td>\n          <td class=\"paramtype\">size_t&nbsp;</td>\n          <td class=\"paramname\"> <em>buffer_size</em></td><td>&nbsp;</td>\n        </tr>\n        <tr>\n          <td></td>\n          <td>)</td>\n          <td></td><td></td><td></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Get username of the user that will be logged in via <a class=\"el\" href=\"group__session.html#gae1bc9bebd230226c3d48925cd1be6edf\">sp_session_relogin()</a></p>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>session</em>&nbsp;</td><td>Your session object </td></tr>\n    <tr><td valign=\"top\"><tt>[out]</tt>&nbsp;</td><td valign=\"top\"><em>buffer</em>&nbsp;</td><td>The buffer to hold the username </td></tr>\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>buffer_size</em>&nbsp;</td><td>The max size of the buffer that will hold the username. The resulting string is guaranteed to always be null terminated if buffer_size &gt; 0</td></tr>\n  </table>\n  </dd>\n</dl>\n<dl class=\"return\"><dt><b>Returns:</b></dt><dd>The number of characters in the username. If value is greater or equal than <code>buffer_size</code>, output was truncated. If returned value is -1 no credentials are stored in libspotify. </dd></dl>\n\n</div>\n</div>\n<a class=\"anchor\" id=\"ga6f27c55d1ce9f3f794fcce7bee7adfea\"></a><!-- doxytag: member=\"api.h::sp_session_set_cache_size\" ref=\"ga6f27c55d1ce9f3f794fcce7bee7adfea\" args=\"(sp_session *session, size_t size)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\"><a class=\"el\" href=\"group__error.html#gafd27986ce4cd9eeaeca8adda83c9eb6b\">sp_error</a> sp_session_set_cache_size </td>\n          <td>(</td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__types.html#ga70dd19c6f824cf6a159575aa4c128b53\">sp_session</a> *&nbsp;</td>\n          <td class=\"paramname\"> <em>session</em>, </td>\n        </tr>\n        <tr>\n          <td class=\"paramkey\"></td>\n          <td></td>\n          <td class=\"paramtype\">size_t&nbsp;</td>\n          <td class=\"paramname\"> <em>size</em></td><td>&nbsp;</td>\n        </tr>\n        <tr>\n          <td></td>\n          <td>)</td>\n          <td></td><td></td><td></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Set maximum cache size.</p>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>session</em>&nbsp;</td><td>Your session object </td></tr>\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>size</em>&nbsp;</td><td>Maximum cache size in megabytes. Setting it to 0 (the default) will let libspotify automatically resize the cache (10% of disk free space) </td></tr>\n  </table>\n  </dd>\n</dl>\n<dl class=\"return\"><dt><b>Returns:</b></dt><dd>One of the following errors, from <a class=\"el\" href=\"group__error.html#ga83154178d3a32668658734d2facfa22b\">sp_error</a> SP_ERROR_OK </dd></dl>\n\n</div>\n</div>\n<a class=\"anchor\" id=\"ga0ac85299c37710321b6d64713e1d6ba8\"></a><!-- doxytag: member=\"api.h::sp_session_set_connection_rules\" ref=\"ga0ac85299c37710321b6d64713e1d6ba8\" args=\"(sp_session *session, sp_connection_rules rules)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\"><a class=\"el\" href=\"group__error.html#gafd27986ce4cd9eeaeca8adda83c9eb6b\">sp_error</a> sp_session_set_connection_rules </td>\n          <td>(</td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__types.html#ga70dd19c6f824cf6a159575aa4c128b53\">sp_session</a> *&nbsp;</td>\n          <td class=\"paramname\"> <em>session</em>, </td>\n        </tr>\n        <tr>\n          <td class=\"paramkey\"></td>\n          <td></td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__session.html#gad275d696685b2ad9ff1a2c3e16af6502\">sp_connection_rules</a>&nbsp;</td>\n          <td class=\"paramname\"> <em>rules</em></td><td>&nbsp;</td>\n        </tr>\n        <tr>\n          <td></td>\n          <td>)</td>\n          <td></td><td></td><td></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Set rules for how libspotify connects to Spotify servers and synchronizes offline content</p>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>session</em>&nbsp;</td><td>Session object </td></tr>\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>rules</em>&nbsp;</td><td>Connection rules</td></tr>\n  </table>\n  </dd>\n</dl>\n<dl class=\"note\"><dt><b>Note:</b></dt><dd>Used in conjunction with <a class=\"el\" href=\"group__session.html#gaf81c61799e0ccdbba048fb79ec050930\">sp_session_set_connection_type()</a> to control how libspotify should behave in respect to network activity and offline synchronization. </dd></dl>\n<dl class=\"see\"><dt><b>See also:</b></dt><dd><a class=\"el\" href=\"group__session.html#ga24ee483cdceef9af3b415c020b197a75\">sp_connection_rules</a> </dd></dl>\n<dl class=\"return\"><dt><b>Returns:</b></dt><dd>One of the following errors, from <a class=\"el\" href=\"group__error.html#ga83154178d3a32668658734d2facfa22b\">sp_error</a> SP_ERROR_OK </dd></dl>\n\n</div>\n</div>\n<a class=\"anchor\" id=\"gaf81c61799e0ccdbba048fb79ec050930\"></a><!-- doxytag: member=\"api.h::sp_session_set_connection_type\" ref=\"gaf81c61799e0ccdbba048fb79ec050930\" args=\"(sp_session *session, sp_connection_type type)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\"><a class=\"el\" href=\"group__error.html#gafd27986ce4cd9eeaeca8adda83c9eb6b\">sp_error</a> sp_session_set_connection_type </td>\n          <td>(</td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__types.html#ga70dd19c6f824cf6a159575aa4c128b53\">sp_session</a> *&nbsp;</td>\n          <td class=\"paramname\"> <em>session</em>, </td>\n        </tr>\n        <tr>\n          <td class=\"paramkey\"></td>\n          <td></td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__session.html#ga3e8773baeb94189b9a1ff27d6a5e3553\">sp_connection_type</a>&nbsp;</td>\n          <td class=\"paramname\"> <em>type</em></td><td>&nbsp;</td>\n        </tr>\n        <tr>\n          <td></td>\n          <td>)</td>\n          <td></td><td></td><td></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Set to true if the connection is currently routed over a roamed connectivity</p>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>session</em>&nbsp;</td><td>Session object </td></tr>\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>type</em>&nbsp;</td><td>Connection type</td></tr>\n  </table>\n  </dd>\n</dl>\n<dl class=\"note\"><dt><b>Note:</b></dt><dd>Used in conjunction with <a class=\"el\" href=\"group__session.html#ga0ac85299c37710321b6d64713e1d6ba8\">sp_session_set_connection_rules()</a> to control how libspotify should behave in respect to network activity and offline synchronization. </dd></dl>\n<dl class=\"see\"><dt><b>See also:</b></dt><dd><a class=\"el\" href=\"group__session.html#ga05a7dbb946a9c47bf011f3f3d77964c3\">sp_connection_type</a> </dd></dl>\n<dl class=\"return\"><dt><b>Returns:</b></dt><dd>One of the following errors, from <a class=\"el\" href=\"group__error.html#ga83154178d3a32668658734d2facfa22b\">sp_error</a> SP_ERROR_OK </dd></dl>\n\n</div>\n</div>\n<a class=\"anchor\" id=\"ga42a8f0999316ac7f141926092879ad2f\"></a><!-- doxytag: member=\"api.h::sp_session_set_private_session\" ref=\"ga42a8f0999316ac7f141926092879ad2f\" args=\"(sp_session *session, bool enabled)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\"><a class=\"el\" href=\"group__error.html#gafd27986ce4cd9eeaeca8adda83c9eb6b\">sp_error</a> sp_session_set_private_session </td>\n          <td>(</td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__types.html#ga70dd19c6f824cf6a159575aa4c128b53\">sp_session</a> *&nbsp;</td>\n          <td class=\"paramname\"> <em>session</em>, </td>\n        </tr>\n        <tr>\n          <td class=\"paramkey\"></td>\n          <td></td>\n          <td class=\"paramtype\">bool&nbsp;</td>\n          <td class=\"paramname\"> <em>enabled</em></td><td>&nbsp;</td>\n        </tr>\n        <tr>\n          <td></td>\n          <td>)</td>\n          <td></td><td></td><td></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Set if private session is enabled. This disables sharing what the user is listening to to services such as Spotify Social, Facebook and LastFM. The private session will last for a time, and then libspotify will revert to the normal state. The private session is prolonged by user activity.</p>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>session</em>&nbsp;</td><td>Session object </td></tr>\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>enabled</em>&nbsp;</td><td>True iff private session should be enabled </td></tr>\n  </table>\n  </dd>\n</dl>\n<dl class=\"return\"><dt><b>Returns:</b></dt><dd>One of the following errors, from <a class=\"el\" href=\"group__error.html#ga83154178d3a32668658734d2facfa22b\">sp_error</a> SP_ERROR_OK </dd></dl>\n\n</div>\n</div>\n<a class=\"anchor\" id=\"ga2475a1fbc2eeacccb96b7f36efd36725\"></a><!-- doxytag: member=\"api.h::sp_session_set_scrobbling\" ref=\"ga2475a1fbc2eeacccb96b7f36efd36725\" args=\"(sp_session *session, sp_social_provider provider, sp_scrobbling_state state)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\"><a class=\"el\" href=\"group__error.html#gafd27986ce4cd9eeaeca8adda83c9eb6b\">sp_error</a> sp_session_set_scrobbling </td>\n          <td>(</td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__types.html#ga70dd19c6f824cf6a159575aa4c128b53\">sp_session</a> *&nbsp;</td>\n          <td class=\"paramname\"> <em>session</em>, </td>\n        </tr>\n        <tr>\n          <td class=\"paramkey\"></td>\n          <td></td>\n          <td class=\"paramtype\">sp_social_provider&nbsp;</td>\n          <td class=\"paramname\"> <em>provider</em>, </td>\n        </tr>\n        <tr>\n          <td class=\"paramkey\"></td>\n          <td></td>\n          <td class=\"paramtype\">sp_scrobbling_state&nbsp;</td>\n          <td class=\"paramname\"> <em>state</em></td><td>&nbsp;</td>\n        </tr>\n        <tr>\n          <td></td>\n          <td>)</td>\n          <td></td><td></td><td></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Set if scrobbling is enabled. This api allows setting local overrides of the global scrobbling settings. Changing the global settings are currently not supported.</p>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>session</em>&nbsp;</td><td>Session object </td></tr>\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>provider</em>&nbsp;</td><td>The scrobbling provider referred to </td></tr>\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>state</em>&nbsp;</td><td>The state to set the provider to</td></tr>\n  </table>\n  </dd>\n</dl>\n<dl class=\"return\"><dt><b>Returns:</b></dt><dd>error code</dd></dl>\n<dl class=\"see\"><dt><b>See also:</b></dt><dd>sp_social_provider </dd>\n<dd>\nsp_scrobbling_state </dd></dl>\n\n</div>\n</div>\n<a class=\"anchor\" id=\"ga9e5ee46ef5e75aa462607caac984f2de\"></a><!-- doxytag: member=\"api.h::sp_session_set_social_credentials\" ref=\"ga9e5ee46ef5e75aa462607caac984f2de\" args=\"(sp_session *session, sp_social_provider provider, const char *username, const char *password)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\"><a class=\"el\" href=\"group__error.html#gafd27986ce4cd9eeaeca8adda83c9eb6b\">sp_error</a> sp_session_set_social_credentials </td>\n          <td>(</td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__types.html#ga70dd19c6f824cf6a159575aa4c128b53\">sp_session</a> *&nbsp;</td>\n          <td class=\"paramname\"> <em>session</em>, </td>\n        </tr>\n        <tr>\n          <td class=\"paramkey\"></td>\n          <td></td>\n          <td class=\"paramtype\">sp_social_provider&nbsp;</td>\n          <td class=\"paramname\"> <em>provider</em>, </td>\n        </tr>\n        <tr>\n          <td class=\"paramkey\"></td>\n          <td></td>\n          <td class=\"paramtype\">const char *&nbsp;</td>\n          <td class=\"paramname\"> <em>username</em>, </td>\n        </tr>\n        <tr>\n          <td class=\"paramkey\"></td>\n          <td></td>\n          <td class=\"paramtype\">const char *&nbsp;</td>\n          <td class=\"paramname\"> <em>password</em></td><td>&nbsp;</td>\n        </tr>\n        <tr>\n          <td></td>\n          <td>)</td>\n          <td></td><td></td><td></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Set the user's credentials with a social provider. Currently this is only relevant for LastFm Call sp_session_set_scrobbling to force an authentication attempt with the LastFm server. If authentication fails a scrobble_error callback will be sent.</p>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>session</em>&nbsp;</td><td>Session object </td></tr>\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>provider</em>&nbsp;</td><td>The scrobbling provider referred to </td></tr>\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>username</em>&nbsp;</td><td>The user name </td></tr>\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>password</em>&nbsp;</td><td>The password</td></tr>\n  </table>\n  </dd>\n</dl>\n<dl class=\"return\"><dt><b>Returns:</b></dt><dd>error code</dd></dl>\n<dl class=\"see\"><dt><b>See also:</b></dt><dd><a class=\"el\" href=\"group__session.html#ga2475a1fbc2eeacccb96b7f36efd36725\">sp_session_set_scrobbling</a> </dd>\n<dd>\n<a class=\"el\" href=\"structsp__session__callbacks.html#a01a47778439fa233187fdefa75a0f7dc\">sp_session_callbacks::scrobble_error</a> </dd></dl>\n<dl class=\"return\"><dt><b>Returns:</b></dt><dd>One of the following errors, from <a class=\"el\" href=\"group__error.html#ga83154178d3a32668658734d2facfa22b\">sp_error</a> SP_ERROR_OK </dd></dl>\n\n</div>\n</div>\n<a class=\"anchor\" id=\"ga4e14f58356d00e3693be84623bf6bd11\"></a><!-- doxytag: member=\"api.h::sp_session_set_volume_normalization\" ref=\"ga4e14f58356d00e3693be84623bf6bd11\" args=\"(sp_session *session, bool on)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\"><a class=\"el\" href=\"group__error.html#gafd27986ce4cd9eeaeca8adda83c9eb6b\">sp_error</a> sp_session_set_volume_normalization </td>\n          <td>(</td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__types.html#ga70dd19c6f824cf6a159575aa4c128b53\">sp_session</a> *&nbsp;</td>\n          <td class=\"paramname\"> <em>session</em>, </td>\n        </tr>\n        <tr>\n          <td class=\"paramkey\"></td>\n          <td></td>\n          <td class=\"paramtype\">bool&nbsp;</td>\n          <td class=\"paramname\"> <em>on</em></td><td>&nbsp;</td>\n        </tr>\n        <tr>\n          <td></td>\n          <td>)</td>\n          <td></td><td></td><td></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Set volume normalization</p>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>session</em>&nbsp;</td><td>Session object </td></tr>\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>on</em>&nbsp;</td><td>True iff volume normalization should be enabled </td></tr>\n  </table>\n  </dd>\n</dl>\n<dl class=\"return\"><dt><b>Returns:</b></dt><dd>One of the following errors, from <a class=\"el\" href=\"group__error.html#ga83154178d3a32668658734d2facfa22b\">sp_error</a> SP_ERROR_OK </dd></dl>\n\n</div>\n</div>\n<a class=\"anchor\" id=\"ga02391c9e28cff0a602f7139542e0238f\"></a><!-- doxytag: member=\"api.h::sp_session_starred_create\" ref=\"ga02391c9e28cff0a602f7139542e0238f\" args=\"(sp_session *session)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\"><a class=\"el\" href=\"group__types.html#ga1bcf54cbc117a20ab2c15e59eb3a8174\">sp_playlist</a>* sp_session_starred_create </td>\n          <td>(</td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__types.html#ga70dd19c6f824cf6a159575aa4c128b53\">sp_session</a> *&nbsp;</td>\n          <td class=\"paramname\"> <em>session</em></td>\n          <td>&nbsp;)&nbsp;</td>\n          <td></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Returns the starred list for the current user</p>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>session</em>&nbsp;</td><td>Session object</td></tr>\n  </table>\n  </dd>\n</dl>\n<dl class=\"return\"><dt><b>Returns:</b></dt><dd>A playlist or NULL if no user is logged in </dd></dl>\n<dl class=\"note\"><dt><b>Note:</b></dt><dd>You need to release the playlist when you are done with it. </dd></dl>\n<dl class=\"see\"><dt><b>See also:</b></dt><dd><a class=\"el\" href=\"group__playlist.html#gacb9250eb530869b039541a8b62dfab6c\">sp_playlist_release()</a> </dd></dl>\n\n</div>\n</div>\n<a class=\"anchor\" id=\"ga9be806a719a6399bfe1fd0d4c125e0eb\"></a><!-- doxytag: member=\"api.h::sp_session_starred_for_user_create\" ref=\"ga9be806a719a6399bfe1fd0d4c125e0eb\" args=\"(sp_session *session, const char *canonical_username)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\"><a class=\"el\" href=\"group__types.html#ga1bcf54cbc117a20ab2c15e59eb3a8174\">sp_playlist</a>* sp_session_starred_for_user_create </td>\n          <td>(</td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__types.html#ga70dd19c6f824cf6a159575aa4c128b53\">sp_session</a> *&nbsp;</td>\n          <td class=\"paramname\"> <em>session</em>, </td>\n        </tr>\n        <tr>\n          <td class=\"paramkey\"></td>\n          <td></td>\n          <td class=\"paramtype\">const char *&nbsp;</td>\n          <td class=\"paramname\"> <em>canonical_username</em></td><td>&nbsp;</td>\n        </tr>\n        <tr>\n          <td></td>\n          <td>)</td>\n          <td></td><td></td><td></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Returns the starred list for a user</p>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>session</em>&nbsp;</td><td>Session object </td></tr>\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>canonical_username</em>&nbsp;</td><td>Canonical username</td></tr>\n  </table>\n  </dd>\n</dl>\n<dl class=\"return\"><dt><b>Returns:</b></dt><dd>A playlist or NULL if no user is logged in </dd></dl>\n<dl class=\"note\"><dt><b>Note:</b></dt><dd>You need to release the playlist when you are done with it. </dd></dl>\n<dl class=\"see\"><dt><b>See also:</b></dt><dd><a class=\"el\" href=\"group__playlist.html#gacb9250eb530869b039541a8b62dfab6c\">sp_playlist_release()</a> </dd></dl>\n\n</div>\n</div>\n<a class=\"anchor\" id=\"ga267bbcae24b6bb1fd56de56678a5f455\"></a><!-- doxytag: member=\"api.h::sp_session_user\" ref=\"ga267bbcae24b6bb1fd56de56678a5f455\" args=\"(sp_session *session)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\"><a class=\"el\" href=\"group__types.html#gaed2dbaa1eebd6752f76613daad9158bc\">sp_user</a>* sp_session_user </td>\n          <td>(</td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__types.html#ga70dd19c6f824cf6a159575aa4c128b53\">sp_session</a> *&nbsp;</td>\n          <td class=\"paramname\"> <em>session</em></td>\n          <td>&nbsp;)&nbsp;</td>\n          <td></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Fetches the currently logged in user</p>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>session</em>&nbsp;</td><td>Your session object</td></tr>\n  </table>\n  </dd>\n</dl>\n<dl class=\"return\"><dt><b>Returns:</b></dt><dd>The logged in user (or NULL if not logged in) </dd></dl>\n\n</div>\n</div>\n<a class=\"anchor\" id=\"ga54c7693afa9be664f3ea870feb0df8d9\"></a><!-- doxytag: member=\"api.h::sp_session_user_country\" ref=\"ga54c7693afa9be664f3ea870feb0df8d9\" args=\"(sp_session *session)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\">int sp_session_user_country </td>\n          <td>(</td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__types.html#ga70dd19c6f824cf6a159575aa4c128b53\">sp_session</a> *&nbsp;</td>\n          <td class=\"paramname\"> <em>session</em></td>\n          <td>&nbsp;)&nbsp;</td>\n          <td></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Get currently logged in users country updated the offline_status_updated() callback will be invoked.</p>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>session</em>&nbsp;</td><td>Session object</td></tr>\n  </table>\n  </dd>\n</dl>\n<dl class=\"return\"><dt><b>Returns:</b></dt><dd>Country encoded in an integer 'SE' = 'S' &lt;&lt; 8 | 'E' </dd></dl>\n\n</div>\n</div>\n<a class=\"anchor\" id=\"gac7a365c2166738909cdb901edebc3f70\"></a><!-- doxytag: member=\"api.h::sp_session_user_name\" ref=\"gac7a365c2166738909cdb901edebc3f70\" args=\"(sp_session *session)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\">const char* sp_session_user_name </td>\n          <td>(</td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__types.html#ga70dd19c6f824cf6a159575aa4c128b53\">sp_session</a> *&nbsp;</td>\n          <td class=\"paramname\"> <em>session</em></td>\n          <td>&nbsp;)&nbsp;</td>\n          <td></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Get a pointer to a string representing the user's login username.</p>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>session</em>&nbsp;</td><td>Your session object</td></tr>\n  </table>\n  </dd>\n</dl>\n<dl class=\"return\"><dt><b>Returns:</b></dt><dd>A string representing the login username. </dd></dl>\n\n</div>\n</div>\n<a class=\"anchor\" id=\"gabfb3f59b20ae0b225e154eb9095152b2\"></a><!-- doxytag: member=\"api.h::sp_session_userdata\" ref=\"gabfb3f59b20ae0b225e154eb9095152b2\" args=\"(sp_session *session)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\">void* sp_session_userdata </td>\n          <td>(</td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__types.html#ga70dd19c6f824cf6a159575aa4c128b53\">sp_session</a> *&nbsp;</td>\n          <td class=\"paramname\"> <em>session</em></td>\n          <td>&nbsp;)&nbsp;</td>\n          <td></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>The userdata associated with the session</p>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>session</em>&nbsp;</td><td>Your session object</td></tr>\n  </table>\n  </dd>\n</dl>\n<dl class=\"return\"><dt><b>Returns:</b></dt><dd>The userdata that was passed in on session creation </dd></dl>\n\n</div>\n</div>\n</div>\n<hr size=\"1\"><address style=\"text-align: right;\"><small>\nGenerated on Wed Jun 13 2012 14:22:40.<br>\nCopyright &copy; 2006&ndash;2012 Spotify Ltd</small></address>\n</body>\n</html>\n"
  },
  {
    "path": "libspotify/docs/html/group__toplist.html",
    "content": "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\n<html xmlns=\"http://www.w3.org/1999/xhtml\">\n<head>\n<meta http-equiv=\"Content-Type\" content=\"text/xhtml;charset=UTF-8\"/>\n<title>libspotify: Toplist handling</title>\n<link href=\"tabs.css\" rel=\"stylesheet\" type=\"text/css\"/>\n<link href=\"doxygen.css\" rel=\"stylesheet\" type=\"text/css\"/>\n</head>\n<body>\n<!-- Generated by Doxygen 1.7.1 -->\n<div class=\"navigation\" id=\"top\">\n  <div class=\"tabs\">\n    <ul class=\"tablist\">\n      <li><a href=\"index.html\"><span>Main&nbsp;Page</span></a></li>\n      <li><a href=\"modules.html\"><span>Modules</span></a></li>\n      <li><a href=\"annotated.html\"><span>Data&nbsp;Structures</span></a></li>\n      <li><a href=\"files.html\"><span>Files</span></a></li>\n      <li><a href=\"examples.html\"><span>Examples</span></a></li>\n    </ul>\n  </div>\n</div>\n<div class=\"header\">\n  <div class=\"summary\">\n<a href=\"#define-members\">Defines</a> &#124;\n<a href=\"#typedef-members\">Typedefs</a> &#124;\n<a href=\"#enum-members\">Enumerations</a> &#124;\n<a href=\"#func-members\">Functions</a>  </div>\n  <div class=\"headertitle\">\n<h1>Toplist handling</h1>  </div>\n</div>\n<div class=\"contents\">\n<table class=\"memberdecls\">\n<tr><td colspan=\"2\"><h2><a name=\"define-members\"></a>\nDefines</h2></td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">#define&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__toplist.html#gaa078b44491f976af43e4941fd1dd032c\">SP_TOPLIST_REGION</a>(a, b)&nbsp;&nbsp;&nbsp;((a) &lt;&lt; 8 | (b))</td></tr>\n<tr><td colspan=\"2\"><h2><a name=\"typedef-members\"></a>\nTypedefs</h2></td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">typedef void&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__toplist.html#gafe8e94ae23133105f35c03b9e3836a0a\">toplistbrowse_complete_cb</a> (<a class=\"el\" href=\"group__types.html#ga723de429cd073bcf5d13fb4e0f466ffd\">sp_toplistbrowse</a> *result, void *userdata)</td></tr>\n<tr><td colspan=\"2\"><h2><a name=\"enum-members\"></a>\nEnumerations</h2></td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">enum &nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__toplist.html#ga220f32522efb2828e4f8ffb949af234a\">sp_toplisttype</a> { <br/>\n&nbsp;&nbsp;<a class=\"el\" href=\"group__toplist.html#gga220f32522efb2828e4f8ffb949af234aa41523e58badf9e3901beea3f53e5d28e\">SP_TOPLIST_TYPE_ARTISTS</a> =  0, \n<br/>\n&nbsp;&nbsp;<a class=\"el\" href=\"group__toplist.html#gga220f32522efb2828e4f8ffb949af234aae8002818ef10eb2c75ec2058ce11cf6b\">SP_TOPLIST_TYPE_ALBUMS</a> =  1, \n<br/>\n&nbsp;&nbsp;<a class=\"el\" href=\"group__toplist.html#gga220f32522efb2828e4f8ffb949af234aa6a85f8384ec77cb9cb5746966b0f0e28\">SP_TOPLIST_TYPE_TRACKS</a> =  2\n<br/>\n }</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">enum &nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__toplist.html#ga6fa5cfed2cbb33f2f64542d0b63f6c8d\">sp_toplistregion</a> { <br/>\n&nbsp;&nbsp;<a class=\"el\" href=\"group__toplist.html#gga6fa5cfed2cbb33f2f64542d0b63f6c8da9e9136541401041c7d5c37708b7a927f\">SP_TOPLIST_REGION_EVERYWHERE</a> =  0, \n<br/>\n&nbsp;&nbsp;<a class=\"el\" href=\"group__toplist.html#gga6fa5cfed2cbb33f2f64542d0b63f6c8da6912eff58c71f5c74b78f48af5305375\">SP_TOPLIST_REGION_USER</a> =  1\n<br/>\n }</td></tr>\n<tr><td colspan=\"2\"><h2><a name=\"func-members\"></a>\nFunctions</h2></td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__types.html#ga723de429cd073bcf5d13fb4e0f466ffd\">sp_toplistbrowse</a> *&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__toplist.html#gac2fe366e0050747438e09cdd22ed0e31\">sp_toplistbrowse_create</a> (<a class=\"el\" href=\"group__types.html#ga70dd19c6f824cf6a159575aa4c128b53\">sp_session</a> *session, <a class=\"el\" href=\"group__toplist.html#ga220f32522efb2828e4f8ffb949af234a\">sp_toplisttype</a> type, <a class=\"el\" href=\"group__toplist.html#ga6fa5cfed2cbb33f2f64542d0b63f6c8d\">sp_toplistregion</a> region, const char *username, <a class=\"el\" href=\"group__toplist.html#gafe8e94ae23133105f35c03b9e3836a0a\">toplistbrowse_complete_cb</a> *callback, void *userdata)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">bool&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__toplist.html#gaff81156c09d311c4f6a82d28a32d7968\">sp_toplistbrowse_is_loaded</a> (<a class=\"el\" href=\"group__types.html#ga723de429cd073bcf5d13fb4e0f466ffd\">sp_toplistbrowse</a> *tlb)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__error.html#gafd27986ce4cd9eeaeca8adda83c9eb6b\">sp_error</a>&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__toplist.html#ga9b881929e74d97f64814ae54953ce4d7\">sp_toplistbrowse_error</a> (<a class=\"el\" href=\"group__types.html#ga723de429cd073bcf5d13fb4e0f466ffd\">sp_toplistbrowse</a> *tlb)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__error.html#gafd27986ce4cd9eeaeca8adda83c9eb6b\">sp_error</a>&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__toplist.html#ga421a19f128e5f3ae4b36e63a133a2a83\">sp_toplistbrowse_add_ref</a> (<a class=\"el\" href=\"group__types.html#ga723de429cd073bcf5d13fb4e0f466ffd\">sp_toplistbrowse</a> *tlb)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__error.html#gafd27986ce4cd9eeaeca8adda83c9eb6b\">sp_error</a>&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__toplist.html#gac6cf969c9cb6b431aeaa4723820ca8de\">sp_toplistbrowse_release</a> (<a class=\"el\" href=\"group__types.html#ga723de429cd073bcf5d13fb4e0f466ffd\">sp_toplistbrowse</a> *tlb)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">int&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__toplist.html#gae2f5c09fbbf947834b1b1e73461f1fb3\">sp_toplistbrowse_num_artists</a> (<a class=\"el\" href=\"group__types.html#ga723de429cd073bcf5d13fb4e0f466ffd\">sp_toplistbrowse</a> *tlb)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__types.html#ga31764fbd69618c10be173c6c03d4c1bc\">sp_artist</a> *&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__toplist.html#ga504cc45074d40c817dffbcc2906ef57f\">sp_toplistbrowse_artist</a> (<a class=\"el\" href=\"group__types.html#ga723de429cd073bcf5d13fb4e0f466ffd\">sp_toplistbrowse</a> *tlb, int index)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">int&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__toplist.html#ga69f5e70269c1eb08e1ddb1c77bb8c3e3\">sp_toplistbrowse_num_albums</a> (<a class=\"el\" href=\"group__types.html#ga723de429cd073bcf5d13fb4e0f466ffd\">sp_toplistbrowse</a> *tlb)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__types.html#ga6fd3e5de729c429fef3ff18ece6dcfad\">sp_album</a> *&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__toplist.html#gaa080ace445d269f56942ac3d7f1f157e\">sp_toplistbrowse_album</a> (<a class=\"el\" href=\"group__types.html#ga723de429cd073bcf5d13fb4e0f466ffd\">sp_toplistbrowse</a> *tlb, int index)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">int&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__toplist.html#gaeb0ddfd565474dc7e444aabebbc119b7\">sp_toplistbrowse_num_tracks</a> (<a class=\"el\" href=\"group__types.html#ga723de429cd073bcf5d13fb4e0f466ffd\">sp_toplistbrowse</a> *tlb)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__types.html#ga47bbd2262f0c8b5d7147af7d62198e48\">sp_track</a> *&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__toplist.html#gaf3d00b8bf089134a4f320a8d3d6ab683\">sp_toplistbrowse_track</a> (<a class=\"el\" href=\"group__types.html#ga723de429cd073bcf5d13fb4e0f466ffd\">sp_toplistbrowse</a> *tlb, int index)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">int&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__toplist.html#gab9cf87d6b6a8cbd8d36cd6e94a3270ee\">sp_toplistbrowse_backend_request_duration</a> (<a class=\"el\" href=\"group__types.html#ga723de429cd073bcf5d13fb4e0f466ffd\">sp_toplistbrowse</a> *tlb)</td></tr>\n</table>\n<hr/><h2>Define Documentation</h2>\n<a class=\"anchor\" id=\"gaa078b44491f976af43e4941fd1dd032c\"></a><!-- doxytag: member=\"api.h::SP_TOPLIST_REGION\" ref=\"gaa078b44491f976af43e4941fd1dd032c\" args=\"(a, b)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\">#define SP_TOPLIST_REGION</td>\n          <td>(</td>\n          <td class=\"paramtype\">&nbsp;</td>\n          <td class=\"paramname\">a, </td>\n        </tr>\n        <tr>\n          <td class=\"paramkey\"></td>\n          <td></td>\n          <td class=\"paramtype\">&nbsp;</td>\n          <td class=\"paramname\">b</td><td>&nbsp;</td>\n        </tr>\n        <tr>\n          <td></td>\n          <td>)</td>\n          <td></td><td></td><td>&nbsp;&nbsp;&nbsp;((a) &lt;&lt; 8 | (b))</td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Convenience macro to create a toplist region. Toplist regions are ISO 3166-1 country codes (in uppercase) encoded in an integer. There are also some reserved codes used to denote non-country regions. See sp_toplistregion</p>\n<p>Example: SP_TOPLIST_REGION('S', 'E') for Sweden </p>\n<dl><dt><b>Examples: </b></dt><dd><a class=\"el\" href=\"toplist_8c-example.html#a14\">toplist.c</a>.</dd>\n</dl>\n</div>\n</div>\n<hr/><h2>Typedef Documentation</h2>\n<a class=\"anchor\" id=\"gafe8e94ae23133105f35c03b9e3836a0a\"></a><!-- doxytag: member=\"api.h::toplistbrowse_complete_cb\" ref=\"gafe8e94ae23133105f35c03b9e3836a0a\" args=\"(sp_toplistbrowse *result, void *userdata)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\">typedef void <a class=\"el\" href=\"group__toplist.html#gafe8e94ae23133105f35c03b9e3836a0a\">toplistbrowse_complete_cb</a>(<a class=\"el\" href=\"group__types.html#ga723de429cd073bcf5d13fb4e0f466ffd\">sp_toplistbrowse</a> *result, void *userdata)</td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>The type of a callback used in <a class=\"el\" href=\"group__toplist.html#gac2fe366e0050747438e09cdd22ed0e31\">sp_toplistbrowse_create()</a></p>\n<p>When the callback is called, the metadata of all tracks belonging to it will have been loaded, so <a class=\"el\" href=\"group__track.html#ga8b69cf193679c7e00031ae43e61c6a54\">sp_track_is_loaded()</a> will return non-zero. The same goes for the similar toplist data.</p>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>result</em>&nbsp;</td><td>The same pointer returned by <a class=\"el\" href=\"group__toplist.html#gac2fe366e0050747438e09cdd22ed0e31\">sp_toplistbrowse_create()</a> </td></tr>\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>userdata</em>&nbsp;</td><td>The opaque pointer given to <a class=\"el\" href=\"group__toplist.html#gac2fe366e0050747438e09cdd22ed0e31\">sp_toplistbrowse_create()</a> </td></tr>\n  </table>\n  </dd>\n</dl>\n\n</div>\n</div>\n<hr/><h2>Enumeration Type Documentation</h2>\n<a class=\"anchor\" id=\"ga6fa5cfed2cbb33f2f64542d0b63f6c8d\"></a><!-- doxytag: member=\"api.h::sp_toplistregion\" ref=\"ga6fa5cfed2cbb33f2f64542d0b63f6c8d\" args=\"\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\">enum <a class=\"el\" href=\"group__toplist.html#ga6fa5cfed2cbb33f2f64542d0b63f6c8d\">sp_toplistregion</a></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Special toplist regions </p>\n<dl><dt><b>Enumerator: </b></dt><dd><table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n<tr><td valign=\"top\"><em><a class=\"anchor\" id=\"gga6fa5cfed2cbb33f2f64542d0b63f6c8da9e9136541401041c7d5c37708b7a927f\"></a><!-- doxytag: member=\"SP_TOPLIST_REGION_EVERYWHERE\" ref=\"gga6fa5cfed2cbb33f2f64542d0b63f6c8da9e9136541401041c7d5c37708b7a927f\" args=\"\" -->SP_TOPLIST_REGION_EVERYWHERE</em>&nbsp;</td><td>\n<p>Global toplist. </p>\n</td></tr>\n<tr><td valign=\"top\"><em><a class=\"anchor\" id=\"gga6fa5cfed2cbb33f2f64542d0b63f6c8da6912eff58c71f5c74b78f48af5305375\"></a><!-- doxytag: member=\"SP_TOPLIST_REGION_USER\" ref=\"gga6fa5cfed2cbb33f2f64542d0b63f6c8da6912eff58c71f5c74b78f48af5305375\" args=\"\" -->SP_TOPLIST_REGION_USER</em>&nbsp;</td><td>\n<p>Toplist for a given user. </p>\n</td></tr>\n</table>\n</dd>\n</dl>\n\n</div>\n</div>\n<a class=\"anchor\" id=\"ga220f32522efb2828e4f8ffb949af234a\"></a><!-- doxytag: member=\"api.h::sp_toplisttype\" ref=\"ga220f32522efb2828e4f8ffb949af234a\" args=\"\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\">enum <a class=\"el\" href=\"group__toplist.html#ga220f32522efb2828e4f8ffb949af234a\">sp_toplisttype</a></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Toplist types </p>\n<dl><dt><b>Enumerator: </b></dt><dd><table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n<tr><td valign=\"top\"><em><a class=\"anchor\" id=\"gga220f32522efb2828e4f8ffb949af234aa41523e58badf9e3901beea3f53e5d28e\"></a><!-- doxytag: member=\"SP_TOPLIST_TYPE_ARTISTS\" ref=\"gga220f32522efb2828e4f8ffb949af234aa41523e58badf9e3901beea3f53e5d28e\" args=\"\" -->SP_TOPLIST_TYPE_ARTISTS</em>&nbsp;</td><td>\n<p>Top artists. </p>\n</td></tr>\n<tr><td valign=\"top\"><em><a class=\"anchor\" id=\"gga220f32522efb2828e4f8ffb949af234aae8002818ef10eb2c75ec2058ce11cf6b\"></a><!-- doxytag: member=\"SP_TOPLIST_TYPE_ALBUMS\" ref=\"gga220f32522efb2828e4f8ffb949af234aae8002818ef10eb2c75ec2058ce11cf6b\" args=\"\" -->SP_TOPLIST_TYPE_ALBUMS</em>&nbsp;</td><td>\n<p>Top albums. </p>\n</td></tr>\n<tr><td valign=\"top\"><em><a class=\"anchor\" id=\"gga220f32522efb2828e4f8ffb949af234aa6a85f8384ec77cb9cb5746966b0f0e28\"></a><!-- doxytag: member=\"SP_TOPLIST_TYPE_TRACKS\" ref=\"gga220f32522efb2828e4f8ffb949af234aa6a85f8384ec77cb9cb5746966b0f0e28\" args=\"\" -->SP_TOPLIST_TYPE_TRACKS</em>&nbsp;</td><td>\n<p>Top tracks. </p>\n</td></tr>\n</table>\n</dd>\n</dl>\n\n</div>\n</div>\n<hr/><h2>Function Documentation</h2>\n<a class=\"anchor\" id=\"ga421a19f128e5f3ae4b36e63a133a2a83\"></a><!-- doxytag: member=\"api.h::sp_toplistbrowse_add_ref\" ref=\"ga421a19f128e5f3ae4b36e63a133a2a83\" args=\"(sp_toplistbrowse *tlb)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\"><a class=\"el\" href=\"group__error.html#gafd27986ce4cd9eeaeca8adda83c9eb6b\">sp_error</a> sp_toplistbrowse_add_ref </td>\n          <td>(</td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__types.html#ga723de429cd073bcf5d13fb4e0f466ffd\">sp_toplistbrowse</a> *&nbsp;</td>\n          <td class=\"paramname\"> <em>tlb</em></td>\n          <td>&nbsp;)&nbsp;</td>\n          <td></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Increase the reference count of an toplist browse result</p>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>tlb</em>&nbsp;</td><td>The toplist browse result object </td></tr>\n  </table>\n  </dd>\n</dl>\n<dl class=\"return\"><dt><b>Returns:</b></dt><dd>One of the following errors, from <a class=\"el\" href=\"group__error.html#ga83154178d3a32668658734d2facfa22b\">sp_error</a> SP_ERROR_OK </dd></dl>\n\n</div>\n</div>\n<a class=\"anchor\" id=\"gaa080ace445d269f56942ac3d7f1f157e\"></a><!-- doxytag: member=\"api.h::sp_toplistbrowse_album\" ref=\"gaa080ace445d269f56942ac3d7f1f157e\" args=\"(sp_toplistbrowse *tlb, int index)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\"><a class=\"el\" href=\"group__types.html#ga6fd3e5de729c429fef3ff18ece6dcfad\">sp_album</a>* sp_toplistbrowse_album </td>\n          <td>(</td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__types.html#ga723de429cd073bcf5d13fb4e0f466ffd\">sp_toplistbrowse</a> *&nbsp;</td>\n          <td class=\"paramname\"> <em>tlb</em>, </td>\n        </tr>\n        <tr>\n          <td class=\"paramkey\"></td>\n          <td></td>\n          <td class=\"paramtype\">int&nbsp;</td>\n          <td class=\"paramname\"> <em>index</em></td><td>&nbsp;</td>\n        </tr>\n        <tr>\n          <td></td>\n          <td>)</td>\n          <td></td><td></td><td></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Return the album at the given index in the given toplist browse object</p>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>tlb</em>&nbsp;</td><td>Toplist object </td></tr>\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>index</em>&nbsp;</td><td>Index of the wanted album. Should be in the interval [0, <a class=\"el\" href=\"group__toplist.html#ga69f5e70269c1eb08e1ddb1c77bb8c3e3\">sp_toplistbrowse_num_albums()</a> - 1]</td></tr>\n  </table>\n  </dd>\n</dl>\n<dl class=\"return\"><dt><b>Returns:</b></dt><dd>The album at the given index in the given toplist browse object </dd></dl>\n<dl><dt><b>Examples: </b></dt><dd><a class=\"el\" href=\"toplist_8c-example.html#a10\">toplist.c</a>.</dd>\n</dl>\n</div>\n</div>\n<a class=\"anchor\" id=\"ga504cc45074d40c817dffbcc2906ef57f\"></a><!-- doxytag: member=\"api.h::sp_toplistbrowse_artist\" ref=\"ga504cc45074d40c817dffbcc2906ef57f\" args=\"(sp_toplistbrowse *tlb, int index)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\"><a class=\"el\" href=\"group__types.html#ga31764fbd69618c10be173c6c03d4c1bc\">sp_artist</a>* sp_toplistbrowse_artist </td>\n          <td>(</td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__types.html#ga723de429cd073bcf5d13fb4e0f466ffd\">sp_toplistbrowse</a> *&nbsp;</td>\n          <td class=\"paramname\"> <em>tlb</em>, </td>\n        </tr>\n        <tr>\n          <td class=\"paramkey\"></td>\n          <td></td>\n          <td class=\"paramtype\">int&nbsp;</td>\n          <td class=\"paramname\"> <em>index</em></td><td>&nbsp;</td>\n        </tr>\n        <tr>\n          <td></td>\n          <td>)</td>\n          <td></td><td></td><td></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Return the artist at the given index in the given toplist browse object</p>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>tlb</em>&nbsp;</td><td>Toplist object </td></tr>\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>index</em>&nbsp;</td><td>Index of the wanted artist. Should be in the interval [0, <a class=\"el\" href=\"group__toplist.html#gae2f5c09fbbf947834b1b1e73461f1fb3\">sp_toplistbrowse_num_artists()</a> - 1]</td></tr>\n  </table>\n  </dd>\n</dl>\n<dl class=\"return\"><dt><b>Returns:</b></dt><dd>The artist at the given index in the given toplist browse object </dd></dl>\n<dl><dt><b>Examples: </b></dt><dd><a class=\"el\" href=\"toplist_8c-example.html#a8\">toplist.c</a>.</dd>\n</dl>\n</div>\n</div>\n<a class=\"anchor\" id=\"gab9cf87d6b6a8cbd8d36cd6e94a3270ee\"></a><!-- doxytag: member=\"api.h::sp_toplistbrowse_backend_request_duration\" ref=\"gab9cf87d6b6a8cbd8d36cd6e94a3270ee\" args=\"(sp_toplistbrowse *tlb)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\">int sp_toplistbrowse_backend_request_duration </td>\n          <td>(</td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__types.html#ga723de429cd073bcf5d13fb4e0f466ffd\">sp_toplistbrowse</a> *&nbsp;</td>\n          <td class=\"paramname\"> <em>tlb</em></td>\n          <td>&nbsp;)&nbsp;</td>\n          <td></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Return the time (in ms) that was spent waiting for the Spotify backend to serve the request</p>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>tlb</em>&nbsp;</td><td>Toplist object</td></tr>\n  </table>\n  </dd>\n</dl>\n<dl class=\"return\"><dt><b>Returns:</b></dt><dd>-1 if the request was served from the local cache If the result is not yet loaded the return value is undefined </dd></dl>\n\n</div>\n</div>\n<a class=\"anchor\" id=\"gac2fe366e0050747438e09cdd22ed0e31\"></a><!-- doxytag: member=\"api.h::sp_toplistbrowse_create\" ref=\"gac2fe366e0050747438e09cdd22ed0e31\" args=\"(sp_session *session, sp_toplisttype type, sp_toplistregion region, const char *username, toplistbrowse_complete_cb *callback, void *userdata)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\"><a class=\"el\" href=\"group__types.html#ga723de429cd073bcf5d13fb4e0f466ffd\">sp_toplistbrowse</a>* sp_toplistbrowse_create </td>\n          <td>(</td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__types.html#ga70dd19c6f824cf6a159575aa4c128b53\">sp_session</a> *&nbsp;</td>\n          <td class=\"paramname\"> <em>session</em>, </td>\n        </tr>\n        <tr>\n          <td class=\"paramkey\"></td>\n          <td></td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__toplist.html#ga220f32522efb2828e4f8ffb949af234a\">sp_toplisttype</a>&nbsp;</td>\n          <td class=\"paramname\"> <em>type</em>, </td>\n        </tr>\n        <tr>\n          <td class=\"paramkey\"></td>\n          <td></td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__toplist.html#ga6fa5cfed2cbb33f2f64542d0b63f6c8d\">sp_toplistregion</a>&nbsp;</td>\n          <td class=\"paramname\"> <em>region</em>, </td>\n        </tr>\n        <tr>\n          <td class=\"paramkey\"></td>\n          <td></td>\n          <td class=\"paramtype\">const char *&nbsp;</td>\n          <td class=\"paramname\"> <em>username</em>, </td>\n        </tr>\n        <tr>\n          <td class=\"paramkey\"></td>\n          <td></td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__toplist.html#gafe8e94ae23133105f35c03b9e3836a0a\">toplistbrowse_complete_cb</a> *&nbsp;</td>\n          <td class=\"paramname\"> <em>callback</em>, </td>\n        </tr>\n        <tr>\n          <td class=\"paramkey\"></td>\n          <td></td>\n          <td class=\"paramtype\">void *&nbsp;</td>\n          <td class=\"paramname\"> <em>userdata</em></td><td>&nbsp;</td>\n        </tr>\n        <tr>\n          <td></td>\n          <td>)</td>\n          <td></td><td></td><td></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Initiate a request for browsing an toplist</p>\n<p>The user is responsible for freeing the returned toplist browse using <a class=\"el\" href=\"group__toplist.html#gac6cf969c9cb6b431aeaa4723820ca8de\">sp_toplistbrowse_release()</a>. This can be done in the callback.</p>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>session</em>&nbsp;</td><td>Session object </td></tr>\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>type</em>&nbsp;</td><td>Type of toplist to be browsed. see the sp_toplisttype enum for possible values </td></tr>\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>region</em>&nbsp;</td><td>Region. see sp_toplistregion enum. Country specific regions are coded as two chars in an integer. Sweden would correspond to 'S' &lt;&lt; 8 | 'E' </td></tr>\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>username</em>&nbsp;</td><td>If region is SP_TOPLIST_REGION_USER this specifies which user to get toplists for. NULL means the logged in user. </td></tr>\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>callback</em>&nbsp;</td><td>Callback to be invoked when browsing has been completed. Pass NULL if you are not interested in this event. </td></tr>\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>userdata</em>&nbsp;</td><td>Userdata passed to callback.</td></tr>\n  </table>\n  </dd>\n</dl>\n<dl class=\"return\"><dt><b>Returns:</b></dt><dd>Toplist browse object</dd></dl>\n<dl class=\"see\"><dt><b>See also:</b></dt><dd><a class=\"el\" href=\"group__toplist.html#gafe8e94ae23133105f35c03b9e3836a0a\">toplistbrowse_complete_cb</a> </dd></dl>\n<dl><dt><b>Examples: </b></dt><dd><a class=\"el\" href=\"toplist_8c-example.html#a15\">toplist.c</a>.</dd>\n</dl>\n</div>\n</div>\n<a class=\"anchor\" id=\"ga9b881929e74d97f64814ae54953ce4d7\"></a><!-- doxytag: member=\"api.h::sp_toplistbrowse_error\" ref=\"ga9b881929e74d97f64814ae54953ce4d7\" args=\"(sp_toplistbrowse *tlb)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\"><a class=\"el\" href=\"group__error.html#gafd27986ce4cd9eeaeca8adda83c9eb6b\">sp_error</a> sp_toplistbrowse_error </td>\n          <td>(</td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__types.html#ga723de429cd073bcf5d13fb4e0f466ffd\">sp_toplistbrowse</a> *&nbsp;</td>\n          <td class=\"paramname\"> <em>tlb</em></td>\n          <td>&nbsp;)&nbsp;</td>\n          <td></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Check if browsing returned an error code.</p>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>tlb</em>&nbsp;</td><td>Toplist browse object</td></tr>\n  </table>\n  </dd>\n</dl>\n<dl class=\"return\"><dt><b>Returns:</b></dt><dd>One of the following errors, from <a class=\"el\" href=\"group__error.html#ga83154178d3a32668658734d2facfa22b\">sp_error</a> SP_ERROR_OK SP_ERROR_IS_LOADING SP_ERROR_OTHER_PERMANENT SP_ERROR_OTHER_TRANSIENT </dd></dl>\n\n</div>\n</div>\n<a class=\"anchor\" id=\"gaff81156c09d311c4f6a82d28a32d7968\"></a><!-- doxytag: member=\"api.h::sp_toplistbrowse_is_loaded\" ref=\"gaff81156c09d311c4f6a82d28a32d7968\" args=\"(sp_toplistbrowse *tlb)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\">bool sp_toplistbrowse_is_loaded </td>\n          <td>(</td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__types.html#ga723de429cd073bcf5d13fb4e0f466ffd\">sp_toplistbrowse</a> *&nbsp;</td>\n          <td class=\"paramname\"> <em>tlb</em></td>\n          <td>&nbsp;)&nbsp;</td>\n          <td></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Check if an toplist browse request is completed</p>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>tlb</em>&nbsp;</td><td>Toplist browse object</td></tr>\n  </table>\n  </dd>\n</dl>\n<dl class=\"return\"><dt><b>Returns:</b></dt><dd>True if browsing is completed, false if not </dd></dl>\n\n</div>\n</div>\n<a class=\"anchor\" id=\"ga69f5e70269c1eb08e1ddb1c77bb8c3e3\"></a><!-- doxytag: member=\"api.h::sp_toplistbrowse_num_albums\" ref=\"ga69f5e70269c1eb08e1ddb1c77bb8c3e3\" args=\"(sp_toplistbrowse *tlb)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\">int sp_toplistbrowse_num_albums </td>\n          <td>(</td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__types.html#ga723de429cd073bcf5d13fb4e0f466ffd\">sp_toplistbrowse</a> *&nbsp;</td>\n          <td class=\"paramname\"> <em>tlb</em></td>\n          <td>&nbsp;)&nbsp;</td>\n          <td></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Given an toplist browse object, return number of albums</p>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>tlb</em>&nbsp;</td><td>Toplist browse object</td></tr>\n  </table>\n  </dd>\n</dl>\n<dl class=\"return\"><dt><b>Returns:</b></dt><dd>Number of albums on toplist </dd></dl>\n<dl><dt><b>Examples: </b></dt><dd><a class=\"el\" href=\"toplist_8c-example.html#a9\">toplist.c</a>.</dd>\n</dl>\n</div>\n</div>\n<a class=\"anchor\" id=\"gae2f5c09fbbf947834b1b1e73461f1fb3\"></a><!-- doxytag: member=\"api.h::sp_toplistbrowse_num_artists\" ref=\"gae2f5c09fbbf947834b1b1e73461f1fb3\" args=\"(sp_toplistbrowse *tlb)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\">int sp_toplistbrowse_num_artists </td>\n          <td>(</td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__types.html#ga723de429cd073bcf5d13fb4e0f466ffd\">sp_toplistbrowse</a> *&nbsp;</td>\n          <td class=\"paramname\"> <em>tlb</em></td>\n          <td>&nbsp;)&nbsp;</td>\n          <td></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Given an toplist browse object, return number of artists</p>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>tlb</em>&nbsp;</td><td>Toplist browse object</td></tr>\n  </table>\n  </dd>\n</dl>\n<dl class=\"return\"><dt><b>Returns:</b></dt><dd>Number of artists on toplist </dd></dl>\n<dl><dt><b>Examples: </b></dt><dd><a class=\"el\" href=\"toplist_8c-example.html#a7\">toplist.c</a>.</dd>\n</dl>\n</div>\n</div>\n<a class=\"anchor\" id=\"gaeb0ddfd565474dc7e444aabebbc119b7\"></a><!-- doxytag: member=\"api.h::sp_toplistbrowse_num_tracks\" ref=\"gaeb0ddfd565474dc7e444aabebbc119b7\" args=\"(sp_toplistbrowse *tlb)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\">int sp_toplistbrowse_num_tracks </td>\n          <td>(</td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__types.html#ga723de429cd073bcf5d13fb4e0f466ffd\">sp_toplistbrowse</a> *&nbsp;</td>\n          <td class=\"paramname\"> <em>tlb</em></td>\n          <td>&nbsp;)&nbsp;</td>\n          <td></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Given an toplist browse object, return number of tracks</p>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>tlb</em>&nbsp;</td><td>Toplist browse object</td></tr>\n  </table>\n  </dd>\n</dl>\n<dl class=\"return\"><dt><b>Returns:</b></dt><dd>Number of tracks on toplist </dd></dl>\n<dl><dt><b>Examples: </b></dt><dd><a class=\"el\" href=\"toplist_8c-example.html#a11\">toplist.c</a>.</dd>\n</dl>\n</div>\n</div>\n<a class=\"anchor\" id=\"gac6cf969c9cb6b431aeaa4723820ca8de\"></a><!-- doxytag: member=\"api.h::sp_toplistbrowse_release\" ref=\"gac6cf969c9cb6b431aeaa4723820ca8de\" args=\"(sp_toplistbrowse *tlb)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\"><a class=\"el\" href=\"group__error.html#gafd27986ce4cd9eeaeca8adda83c9eb6b\">sp_error</a> sp_toplistbrowse_release </td>\n          <td>(</td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__types.html#ga723de429cd073bcf5d13fb4e0f466ffd\">sp_toplistbrowse</a> *&nbsp;</td>\n          <td class=\"paramname\"> <em>tlb</em></td>\n          <td>&nbsp;)&nbsp;</td>\n          <td></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Decrease the reference count of an toplist browse result</p>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>tlb</em>&nbsp;</td><td>The toplist browse result object </td></tr>\n  </table>\n  </dd>\n</dl>\n<dl class=\"return\"><dt><b>Returns:</b></dt><dd>One of the following errors, from <a class=\"el\" href=\"group__error.html#ga83154178d3a32668658734d2facfa22b\">sp_error</a> SP_ERROR_OK </dd></dl>\n<dl><dt><b>Examples: </b></dt><dd><a class=\"el\" href=\"toplist_8c-example.html#a13\">toplist.c</a>.</dd>\n</dl>\n</div>\n</div>\n<a class=\"anchor\" id=\"gaf3d00b8bf089134a4f320a8d3d6ab683\"></a><!-- doxytag: member=\"api.h::sp_toplistbrowse_track\" ref=\"gaf3d00b8bf089134a4f320a8d3d6ab683\" args=\"(sp_toplistbrowse *tlb, int index)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\"><a class=\"el\" href=\"group__types.html#ga47bbd2262f0c8b5d7147af7d62198e48\">sp_track</a>* sp_toplistbrowse_track </td>\n          <td>(</td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__types.html#ga723de429cd073bcf5d13fb4e0f466ffd\">sp_toplistbrowse</a> *&nbsp;</td>\n          <td class=\"paramname\"> <em>tlb</em>, </td>\n        </tr>\n        <tr>\n          <td class=\"paramkey\"></td>\n          <td></td>\n          <td class=\"paramtype\">int&nbsp;</td>\n          <td class=\"paramname\"> <em>index</em></td><td>&nbsp;</td>\n        </tr>\n        <tr>\n          <td></td>\n          <td>)</td>\n          <td></td><td></td><td></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Return the track at the given index in the given toplist browse object</p>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>tlb</em>&nbsp;</td><td>Toplist object </td></tr>\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>index</em>&nbsp;</td><td>Index of the wanted track. Should be in the interval [0, <a class=\"el\" href=\"group__toplist.html#gaeb0ddfd565474dc7e444aabebbc119b7\">sp_toplistbrowse_num_tracks()</a> - 1]</td></tr>\n  </table>\n  </dd>\n</dl>\n<dl class=\"return\"><dt><b>Returns:</b></dt><dd>The track at the given index in the given toplist browse object </dd></dl>\n<dl><dt><b>Examples: </b></dt><dd><a class=\"el\" href=\"toplist_8c-example.html#a12\">toplist.c</a>.</dd>\n</dl>\n</div>\n</div>\n</div>\n<hr size=\"1\"><address style=\"text-align: right;\"><small>\nGenerated on Wed Jun 13 2012 14:22:40.<br>\nCopyright &copy; 2006&ndash;2012 Spotify Ltd</small></address>\n</body>\n</html>\n"
  },
  {
    "path": "libspotify/docs/html/group__track.html",
    "content": "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\n<html xmlns=\"http://www.w3.org/1999/xhtml\">\n<head>\n<meta http-equiv=\"Content-Type\" content=\"text/xhtml;charset=UTF-8\"/>\n<title>libspotify: Track subsystem</title>\n<link href=\"tabs.css\" rel=\"stylesheet\" type=\"text/css\"/>\n<link href=\"doxygen.css\" rel=\"stylesheet\" type=\"text/css\"/>\n</head>\n<body>\n<!-- Generated by Doxygen 1.7.1 -->\n<div class=\"navigation\" id=\"top\">\n  <div class=\"tabs\">\n    <ul class=\"tablist\">\n      <li><a href=\"index.html\"><span>Main&nbsp;Page</span></a></li>\n      <li><a href=\"modules.html\"><span>Modules</span></a></li>\n      <li><a href=\"annotated.html\"><span>Data&nbsp;Structures</span></a></li>\n      <li><a href=\"files.html\"><span>Files</span></a></li>\n      <li><a href=\"examples.html\"><span>Examples</span></a></li>\n    </ul>\n  </div>\n</div>\n<div class=\"header\">\n  <div class=\"summary\">\n<a href=\"#func-members\">Functions</a>  </div>\n  <div class=\"headertitle\">\n<h1>Track subsystem</h1>  </div>\n</div>\n<div class=\"contents\">\n<table class=\"memberdecls\">\n<tr><td colspan=\"2\"><h2><a name=\"func-members\"></a>\nFunctions</h2></td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">bool&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__track.html#ga8b69cf193679c7e00031ae43e61c6a54\">sp_track_is_loaded</a> (<a class=\"el\" href=\"group__types.html#ga47bbd2262f0c8b5d7147af7d62198e48\">sp_track</a> *track)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__error.html#gafd27986ce4cd9eeaeca8adda83c9eb6b\">sp_error</a>&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__track.html#ga947c0f7755b0c4955ca0b0993db0f2b5\">sp_track_error</a> (<a class=\"el\" href=\"group__types.html#ga47bbd2262f0c8b5d7147af7d62198e48\">sp_track</a> *track)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__session.html#gaeaa41aad3c0047409996a6ec3b03203f\">sp_track_offline_status</a>&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__track.html#ga281e0ad4373579c5d24202ea1f93fe7b\">sp_track_offline_get_status</a> (<a class=\"el\" href=\"group__types.html#ga47bbd2262f0c8b5d7147af7d62198e48\">sp_track</a> *track)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__session.html#ga60c7ff53ddbc04c036a23181b7275d69\">sp_track_availability</a>&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__track.html#ga9c78846badae6567fe9f9a3792fd06c8\">sp_track_get_availability</a> (<a class=\"el\" href=\"group__types.html#ga70dd19c6f824cf6a159575aa4c128b53\">sp_session</a> *session, <a class=\"el\" href=\"group__types.html#ga47bbd2262f0c8b5d7147af7d62198e48\">sp_track</a> *track)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">bool&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__track.html#gabcb75da69e0338006bdbd2f2f467f082\">sp_track_is_local</a> (<a class=\"el\" href=\"group__types.html#ga70dd19c6f824cf6a159575aa4c128b53\">sp_session</a> *session, <a class=\"el\" href=\"group__types.html#ga47bbd2262f0c8b5d7147af7d62198e48\">sp_track</a> *track)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">bool&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__track.html#ga4eeb86de13187697cd9dfe0b0934988d\">sp_track_is_autolinked</a> (<a class=\"el\" href=\"group__types.html#ga70dd19c6f824cf6a159575aa4c128b53\">sp_session</a> *session, <a class=\"el\" href=\"group__types.html#ga47bbd2262f0c8b5d7147af7d62198e48\">sp_track</a> *track)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__types.html#ga47bbd2262f0c8b5d7147af7d62198e48\">sp_track</a> *&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__track.html#ga112dca47d0bac39818b55119ef134ffd\">sp_track_get_playable</a> (<a class=\"el\" href=\"group__types.html#ga70dd19c6f824cf6a159575aa4c128b53\">sp_session</a> *session, <a class=\"el\" href=\"group__types.html#ga47bbd2262f0c8b5d7147af7d62198e48\">sp_track</a> *track)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">bool&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__track.html#ga2367d906c578e674d0d470d8c1ee3b33\">sp_track_is_placeholder</a> (<a class=\"el\" href=\"group__types.html#ga47bbd2262f0c8b5d7147af7d62198e48\">sp_track</a> *track)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">bool&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__track.html#gab17d380ac941e102af0f308ad885b3c3\">sp_track_is_starred</a> (<a class=\"el\" href=\"group__types.html#ga70dd19c6f824cf6a159575aa4c128b53\">sp_session</a> *session, <a class=\"el\" href=\"group__types.html#ga47bbd2262f0c8b5d7147af7d62198e48\">sp_track</a> *track)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__error.html#gafd27986ce4cd9eeaeca8adda83c9eb6b\">sp_error</a>&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__track.html#ga34b5a712fb2c683402ff78df73e7545c\">sp_track_set_starred</a> (<a class=\"el\" href=\"group__types.html#ga70dd19c6f824cf6a159575aa4c128b53\">sp_session</a> *session, <a class=\"el\" href=\"group__types.html#ga47bbd2262f0c8b5d7147af7d62198e48\">sp_track</a> *const *tracks, int num_tracks, bool star)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">int&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__track.html#ga0aa945fc43e35d36cc334a52735d83b2\">sp_track_num_artists</a> (<a class=\"el\" href=\"group__types.html#ga47bbd2262f0c8b5d7147af7d62198e48\">sp_track</a> *track)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__types.html#ga31764fbd69618c10be173c6c03d4c1bc\">sp_artist</a> *&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__track.html#ga67cd0c035627a1e4a54642213fdf1d75\">sp_track_artist</a> (<a class=\"el\" href=\"group__types.html#ga47bbd2262f0c8b5d7147af7d62198e48\">sp_track</a> *track, int index)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__types.html#ga6fd3e5de729c429fef3ff18ece6dcfad\">sp_album</a> *&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__track.html#ga39a0f52244472cb2d450ea9ba6807304\">sp_track_album</a> (<a class=\"el\" href=\"group__types.html#ga47bbd2262f0c8b5d7147af7d62198e48\">sp_track</a> *track)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">const char *&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__track.html#ga8eb423d3cc2cbfb743c7f23ffb8d0fad\">sp_track_name</a> (<a class=\"el\" href=\"group__types.html#ga47bbd2262f0c8b5d7147af7d62198e48\">sp_track</a> *track)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">int&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__track.html#gac817937bd8d8355b6a1949b76d0b5560\">sp_track_duration</a> (<a class=\"el\" href=\"group__types.html#ga47bbd2262f0c8b5d7147af7d62198e48\">sp_track</a> *track)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">int&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__track.html#ga4570f08f968edbff519b44d2241d2255\">sp_track_popularity</a> (<a class=\"el\" href=\"group__types.html#ga47bbd2262f0c8b5d7147af7d62198e48\">sp_track</a> *track)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">int&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__track.html#ga9d464ee4a5c8836b59888952b960223a\">sp_track_disc</a> (<a class=\"el\" href=\"group__types.html#ga47bbd2262f0c8b5d7147af7d62198e48\">sp_track</a> *track)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">int&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__track.html#ga25c1df9d32fd58f243397740b29c3f61\">sp_track_index</a> (<a class=\"el\" href=\"group__types.html#ga47bbd2262f0c8b5d7147af7d62198e48\">sp_track</a> *track)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__types.html#ga47bbd2262f0c8b5d7147af7d62198e48\">sp_track</a> *&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__track.html#ga0fb814ef23636fdecda64e3a63b15a23\">sp_localtrack_create</a> (const char *artist, const char *title, const char *album, int length)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__error.html#gafd27986ce4cd9eeaeca8adda83c9eb6b\">sp_error</a>&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__track.html#ga7d86041a2bf75590f55978521c08e38c\">sp_track_add_ref</a> (<a class=\"el\" href=\"group__types.html#ga47bbd2262f0c8b5d7147af7d62198e48\">sp_track</a> *track)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__error.html#gafd27986ce4cd9eeaeca8adda83c9eb6b\">sp_error</a>&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__track.html#gaa11098d82e6c2ae42fc2ea1486e741de\">sp_track_release</a> (<a class=\"el\" href=\"group__types.html#ga47bbd2262f0c8b5d7147af7d62198e48\">sp_track</a> *track)</td></tr>\n</table>\n<hr/><h2>Function Documentation</h2>\n<a class=\"anchor\" id=\"ga0fb814ef23636fdecda64e3a63b15a23\"></a><!-- doxytag: member=\"api.h::sp_localtrack_create\" ref=\"ga0fb814ef23636fdecda64e3a63b15a23\" args=\"(const char *artist, const char *title, const char *album, int length)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\"><a class=\"el\" href=\"group__types.html#ga47bbd2262f0c8b5d7147af7d62198e48\">sp_track</a>* sp_localtrack_create </td>\n          <td>(</td>\n          <td class=\"paramtype\">const char *&nbsp;</td>\n          <td class=\"paramname\"> <em>artist</em>, </td>\n        </tr>\n        <tr>\n          <td class=\"paramkey\"></td>\n          <td></td>\n          <td class=\"paramtype\">const char *&nbsp;</td>\n          <td class=\"paramname\"> <em>title</em>, </td>\n        </tr>\n        <tr>\n          <td class=\"paramkey\"></td>\n          <td></td>\n          <td class=\"paramtype\">const char *&nbsp;</td>\n          <td class=\"paramname\"> <em>album</em>, </td>\n        </tr>\n        <tr>\n          <td class=\"paramkey\"></td>\n          <td></td>\n          <td class=\"paramtype\">int&nbsp;</td>\n          <td class=\"paramname\"> <em>length</em></td><td>&nbsp;</td>\n        </tr>\n        <tr>\n          <td></td>\n          <td>)</td>\n          <td></td><td></td><td></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Returns the newly created local track</p>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>artist</em>&nbsp;</td><td>Name of the artist </td></tr>\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>title</em>&nbsp;</td><td>Song title </td></tr>\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>album</em>&nbsp;</td><td>Name of the album, or an empty string if not available </td></tr>\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>length</em>&nbsp;</td><td>Length in MS, or -1 if not available.</td></tr>\n  </table>\n  </dd>\n</dl>\n<dl class=\"return\"><dt><b>Returns:</b></dt><dd>A track. </dd></dl>\n\n</div>\n</div>\n<a class=\"anchor\" id=\"ga7d86041a2bf75590f55978521c08e38c\"></a><!-- doxytag: member=\"api.h::sp_track_add_ref\" ref=\"ga7d86041a2bf75590f55978521c08e38c\" args=\"(sp_track *track)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\"><a class=\"el\" href=\"group__error.html#gafd27986ce4cd9eeaeca8adda83c9eb6b\">sp_error</a> sp_track_add_ref </td>\n          <td>(</td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__types.html#ga47bbd2262f0c8b5d7147af7d62198e48\">sp_track</a> *&nbsp;</td>\n          <td class=\"paramname\"> <em>track</em></td>\n          <td>&nbsp;)&nbsp;</td>\n          <td></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Increase the reference count of a track</p>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>track</em>&nbsp;</td><td>The track object </td></tr>\n  </table>\n  </dd>\n</dl>\n<dl class=\"return\"><dt><b>Returns:</b></dt><dd>One of the following errors, from <a class=\"el\" href=\"group__error.html#ga83154178d3a32668658734d2facfa22b\">sp_error</a> SP_ERROR_OK </dd></dl>\n<dl><dt><b>Examples: </b></dt><dd><a class=\"el\" href=\"browse_8c-example.html#a57\">browse.c</a>.</dd>\n</dl>\n</div>\n</div>\n<a class=\"anchor\" id=\"ga39a0f52244472cb2d450ea9ba6807304\"></a><!-- doxytag: member=\"api.h::sp_track_album\" ref=\"ga39a0f52244472cb2d450ea9ba6807304\" args=\"(sp_track *track)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\"><a class=\"el\" href=\"group__types.html#ga6fd3e5de729c429fef3ff18ece6dcfad\">sp_album</a>* sp_track_album </td>\n          <td>(</td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__types.html#ga47bbd2262f0c8b5d7147af7d62198e48\">sp_track</a> *&nbsp;</td>\n          <td class=\"paramname\"> <em>track</em></td>\n          <td>&nbsp;)&nbsp;</td>\n          <td></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>The album of the specified track</p>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>track</em>&nbsp;</td><td>A track object</td></tr>\n  </table>\n  </dd>\n</dl>\n<dl class=\"return\"><dt><b>Returns:</b></dt><dd>The album of the given track. You need to increase the refcount if you want to keep the pointer around. If no metadata is available for the track yet, this function returns 0. </dd></dl>\n\n</div>\n</div>\n<a class=\"anchor\" id=\"ga67cd0c035627a1e4a54642213fdf1d75\"></a><!-- doxytag: member=\"api.h::sp_track_artist\" ref=\"ga67cd0c035627a1e4a54642213fdf1d75\" args=\"(sp_track *track, int index)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\"><a class=\"el\" href=\"group__types.html#ga31764fbd69618c10be173c6c03d4c1bc\">sp_artist</a>* sp_track_artist </td>\n          <td>(</td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__types.html#ga47bbd2262f0c8b5d7147af7d62198e48\">sp_track</a> *&nbsp;</td>\n          <td class=\"paramname\"> <em>track</em>, </td>\n        </tr>\n        <tr>\n          <td class=\"paramkey\"></td>\n          <td></td>\n          <td class=\"paramtype\">int&nbsp;</td>\n          <td class=\"paramname\"> <em>index</em></td><td>&nbsp;</td>\n        </tr>\n        <tr>\n          <td></td>\n          <td>)</td>\n          <td></td><td></td><td></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>The artist matching the specified index performing on the current track.</p>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>track</em>&nbsp;</td><td>The track whose participating artist you are interested in </td></tr>\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>index</em>&nbsp;</td><td>The index for the participating artist. Should be in the interval [0, <a class=\"el\" href=\"group__track.html#ga0aa945fc43e35d36cc334a52735d83b2\">sp_track_num_artists()</a> - 1]</td></tr>\n  </table>\n  </dd>\n</dl>\n<dl class=\"return\"><dt><b>Returns:</b></dt><dd>The participating artist, or NULL if invalid index </dd></dl>\n<dl><dt><b>Examples: </b></dt><dd><a class=\"el\" href=\"browse_8c-example.html#a8\">browse.c</a>.</dd>\n</dl>\n</div>\n</div>\n<a class=\"anchor\" id=\"ga9d464ee4a5c8836b59888952b960223a\"></a><!-- doxytag: member=\"api.h::sp_track_disc\" ref=\"ga9d464ee4a5c8836b59888952b960223a\" args=\"(sp_track *track)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\">int sp_track_disc </td>\n          <td>(</td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__types.html#ga47bbd2262f0c8b5d7147af7d62198e48\">sp_track</a> *&nbsp;</td>\n          <td class=\"paramname\"> <em>track</em></td>\n          <td>&nbsp;)&nbsp;</td>\n          <td></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Returns the disc number for a track</p>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>track</em>&nbsp;</td><td>A track object</td></tr>\n  </table>\n  </dd>\n</dl>\n<dl class=\"return\"><dt><b>Returns:</b></dt><dd>Disc index. Possible values are [1, total number of discs on album] This function returns valid data only for tracks appearing in a browse artist or browse album result (otherwise returns 0). </dd></dl>\n<dl><dt><b>Examples: </b></dt><dd><a class=\"el\" href=\"browse_8c-example.html#a6\">browse.c</a>.</dd>\n</dl>\n</div>\n</div>\n<a class=\"anchor\" id=\"gac817937bd8d8355b6a1949b76d0b5560\"></a><!-- doxytag: member=\"api.h::sp_track_duration\" ref=\"gac817937bd8d8355b6a1949b76d0b5560\" args=\"(sp_track *track)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\">int sp_track_duration </td>\n          <td>(</td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__types.html#ga47bbd2262f0c8b5d7147af7d62198e48\">sp_track</a> *&nbsp;</td>\n          <td class=\"paramname\"> <em>track</em></td>\n          <td>&nbsp;)&nbsp;</td>\n          <td></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>The duration, in milliseconds, of the specified track</p>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>track</em>&nbsp;</td><td>A track object</td></tr>\n  </table>\n  </dd>\n</dl>\n<dl class=\"return\"><dt><b>Returns:</b></dt><dd>The duration of the specified track, in milliseconds If no metadata is available for the track yet, this function returns 0. </dd></dl>\n<dl><dt><b>Examples: </b></dt><dd><a class=\"el\" href=\"browse_8c-example.html#a1\">browse.c</a>.</dd>\n</dl>\n</div>\n</div>\n<a class=\"anchor\" id=\"ga947c0f7755b0c4955ca0b0993db0f2b5\"></a><!-- doxytag: member=\"api.h::sp_track_error\" ref=\"ga947c0f7755b0c4955ca0b0993db0f2b5\" args=\"(sp_track *track)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\"><a class=\"el\" href=\"group__error.html#gafd27986ce4cd9eeaeca8adda83c9eb6b\">sp_error</a> sp_track_error </td>\n          <td>(</td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__types.html#ga47bbd2262f0c8b5d7147af7d62198e48\">sp_track</a> *&nbsp;</td>\n          <td class=\"paramname\"> <em>track</em></td>\n          <td>&nbsp;)&nbsp;</td>\n          <td></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Return an error code associated with a track. For example if it could not load</p>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>track</em>&nbsp;</td><td>The track</td></tr>\n  </table>\n  </dd>\n</dl>\n<dl class=\"return\"><dt><b>Returns:</b></dt><dd>One of the following errors, from <a class=\"el\" href=\"group__error.html#ga83154178d3a32668658734d2facfa22b\">sp_error</a> SP_ERROR_OK SP_ERROR_IS_LOADING SP_ERROR_OTHER_PERMANENT </dd></dl>\n<dl><dt><b>Examples: </b></dt><dd><a class=\"el\" href=\"browse_8c-example.html#a34\">browse.c</a>, and <a class=\"el\" href=\"jukebox_8c-example.html#a3\">jukebox.c</a>.</dd>\n</dl>\n</div>\n</div>\n<a class=\"anchor\" id=\"ga9c78846badae6567fe9f9a3792fd06c8\"></a><!-- doxytag: member=\"api.h::sp_track_get_availability\" ref=\"ga9c78846badae6567fe9f9a3792fd06c8\" args=\"(sp_session *session, sp_track *track)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\"><a class=\"el\" href=\"group__session.html#ga60c7ff53ddbc04c036a23181b7275d69\">sp_track_availability</a> sp_track_get_availability </td>\n          <td>(</td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__types.html#ga70dd19c6f824cf6a159575aa4c128b53\">sp_session</a> *&nbsp;</td>\n          <td class=\"paramname\"> <em>session</em>, </td>\n        </tr>\n        <tr>\n          <td class=\"paramkey\"></td>\n          <td></td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__types.html#ga47bbd2262f0c8b5d7147af7d62198e48\">sp_track</a> *&nbsp;</td>\n          <td class=\"paramname\"> <em>track</em></td><td>&nbsp;</td>\n        </tr>\n        <tr>\n          <td></td>\n          <td>)</td>\n          <td></td><td></td><td></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Return availability for a track</p>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>session</em>&nbsp;</td><td>Session </td></tr>\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>track</em>&nbsp;</td><td>The track</td></tr>\n  </table>\n  </dd>\n</dl>\n<dl class=\"return\"><dt><b>Returns:</b></dt><dd>Availability status, see <a class=\"el\" href=\"group__session.html#ga60c7ff53ddbc04c036a23181b7275d69\">sp_track_availability</a></dd></dl>\n<dl class=\"note\"><dt><b>Note:</b></dt><dd>The track must be loaded or this function will always SP_TRACK_AVAILABILITY_UNAVAILABLE </dd></dl>\n<dl class=\"see\"><dt><b>See also:</b></dt><dd><a class=\"el\" href=\"group__track.html#ga8b69cf193679c7e00031ae43e61c6a54\">sp_track_is_loaded()</a> </dd></dl>\n\n</div>\n</div>\n<a class=\"anchor\" id=\"ga112dca47d0bac39818b55119ef134ffd\"></a><!-- doxytag: member=\"api.h::sp_track_get_playable\" ref=\"ga112dca47d0bac39818b55119ef134ffd\" args=\"(sp_session *session, sp_track *track)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\"><a class=\"el\" href=\"group__types.html#ga47bbd2262f0c8b5d7147af7d62198e48\">sp_track</a>* sp_track_get_playable </td>\n          <td>(</td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__types.html#ga70dd19c6f824cf6a159575aa4c128b53\">sp_session</a> *&nbsp;</td>\n          <td class=\"paramname\"> <em>session</em>, </td>\n        </tr>\n        <tr>\n          <td class=\"paramkey\"></td>\n          <td></td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__types.html#ga47bbd2262f0c8b5d7147af7d62198e48\">sp_track</a> *&nbsp;</td>\n          <td class=\"paramname\"> <em>track</em></td><td>&nbsp;</td>\n        </tr>\n        <tr>\n          <td></td>\n          <td>)</td>\n          <td></td><td></td><td></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Return the actual track that will be played if the given track is played</p>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>session</em>&nbsp;</td><td>Session </td></tr>\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>track</em>&nbsp;</td><td>The track</td></tr>\n  </table>\n  </dd>\n</dl>\n<dl class=\"return\"><dt><b>Returns:</b></dt><dd>A track </dd></dl>\n\n</div>\n</div>\n<a class=\"anchor\" id=\"ga25c1df9d32fd58f243397740b29c3f61\"></a><!-- doxytag: member=\"api.h::sp_track_index\" ref=\"ga25c1df9d32fd58f243397740b29c3f61\" args=\"(sp_track *track)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\">int sp_track_index </td>\n          <td>(</td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__types.html#ga47bbd2262f0c8b5d7147af7d62198e48\">sp_track</a> *&nbsp;</td>\n          <td class=\"paramname\"> <em>track</em></td>\n          <td>&nbsp;)&nbsp;</td>\n          <td></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Returns the position of a track on its disc</p>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>track</em>&nbsp;</td><td>A track object</td></tr>\n  </table>\n  </dd>\n</dl>\n<dl class=\"return\"><dt><b>Returns:</b></dt><dd>Track position, starts at 1 (relative the corresponding disc) This function returns valid data only for tracks appearing in a browse artist or browse album result (otherwise returns 0). </dd></dl>\n<dl><dt><b>Examples: </b></dt><dd><a class=\"el\" href=\"browse_8c-example.html#a7\">browse.c</a>.</dd>\n</dl>\n</div>\n</div>\n<a class=\"anchor\" id=\"ga4eeb86de13187697cd9dfe0b0934988d\"></a><!-- doxytag: member=\"api.h::sp_track_is_autolinked\" ref=\"ga4eeb86de13187697cd9dfe0b0934988d\" args=\"(sp_session *session, sp_track *track)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\">bool sp_track_is_autolinked </td>\n          <td>(</td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__types.html#ga70dd19c6f824cf6a159575aa4c128b53\">sp_session</a> *&nbsp;</td>\n          <td class=\"paramname\"> <em>session</em>, </td>\n        </tr>\n        <tr>\n          <td class=\"paramkey\"></td>\n          <td></td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__types.html#ga47bbd2262f0c8b5d7147af7d62198e48\">sp_track</a> *&nbsp;</td>\n          <td class=\"paramname\"> <em>track</em></td><td>&nbsp;</td>\n        </tr>\n        <tr>\n          <td></td>\n          <td>)</td>\n          <td></td><td></td><td></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Return true if the track is autolinked to another track.</p>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>session</em>&nbsp;</td><td>Session </td></tr>\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>track</em>&nbsp;</td><td>The track</td></tr>\n  </table>\n  </dd>\n</dl>\n<dl class=\"return\"><dt><b>Returns:</b></dt><dd>True if track is autolinked.</dd></dl>\n<dl class=\"note\"><dt><b>Note:</b></dt><dd>The track must be loaded or this function will always return false. </dd></dl>\n<dl class=\"see\"><dt><b>See also:</b></dt><dd><a class=\"el\" href=\"group__track.html#ga8b69cf193679c7e00031ae43e61c6a54\">sp_track_is_loaded()</a> </dd></dl>\n\n</div>\n</div>\n<a class=\"anchor\" id=\"ga8b69cf193679c7e00031ae43e61c6a54\"></a><!-- doxytag: member=\"api.h::sp_track_is_loaded\" ref=\"ga8b69cf193679c7e00031ae43e61c6a54\" args=\"(sp_track *track)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\">bool sp_track_is_loaded </td>\n          <td>(</td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__types.html#ga47bbd2262f0c8b5d7147af7d62198e48\">sp_track</a> *&nbsp;</td>\n          <td class=\"paramname\"> <em>track</em></td>\n          <td>&nbsp;)&nbsp;</td>\n          <td></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Return whether or not the track metadata is loaded.</p>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>track</em>&nbsp;</td><td>The track</td></tr>\n  </table>\n  </dd>\n</dl>\n<dl class=\"return\"><dt><b>Returns:</b></dt><dd>True if track is loaded</dd></dl>\n<dl class=\"note\"><dt><b>Note:</b></dt><dd>This is equivalent to checking if <a class=\"el\" href=\"group__track.html#ga947c0f7755b0c4955ca0b0993db0f2b5\">sp_track_error()</a> not returns SP_ERROR_IS_LOADING. </dd></dl>\n<dl><dt><b>Examples: </b></dt><dd><a class=\"el\" href=\"browse_8c-example.html#a40\">browse.c</a>.</dd>\n</dl>\n</div>\n</div>\n<a class=\"anchor\" id=\"gabcb75da69e0338006bdbd2f2f467f082\"></a><!-- doxytag: member=\"api.h::sp_track_is_local\" ref=\"gabcb75da69e0338006bdbd2f2f467f082\" args=\"(sp_session *session, sp_track *track)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\">bool sp_track_is_local </td>\n          <td>(</td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__types.html#ga70dd19c6f824cf6a159575aa4c128b53\">sp_session</a> *&nbsp;</td>\n          <td class=\"paramname\"> <em>session</em>, </td>\n        </tr>\n        <tr>\n          <td class=\"paramkey\"></td>\n          <td></td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__types.html#ga47bbd2262f0c8b5d7147af7d62198e48\">sp_track</a> *&nbsp;</td>\n          <td class=\"paramname\"> <em>track</em></td><td>&nbsp;</td>\n        </tr>\n        <tr>\n          <td></td>\n          <td>)</td>\n          <td></td><td></td><td></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Return true if the track is a local file.</p>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>session</em>&nbsp;</td><td>Session </td></tr>\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>track</em>&nbsp;</td><td>The track</td></tr>\n  </table>\n  </dd>\n</dl>\n<dl class=\"return\"><dt><b>Returns:</b></dt><dd>True if track is a local file.</dd></dl>\n<dl class=\"note\"><dt><b>Note:</b></dt><dd>The track must be loaded or this function will always return false. </dd></dl>\n<dl class=\"see\"><dt><b>See also:</b></dt><dd><a class=\"el\" href=\"group__track.html#ga8b69cf193679c7e00031ae43e61c6a54\">sp_track_is_loaded()</a> </dd></dl>\n\n</div>\n</div>\n<a class=\"anchor\" id=\"ga2367d906c578e674d0d470d8c1ee3b33\"></a><!-- doxytag: member=\"api.h::sp_track_is_placeholder\" ref=\"ga2367d906c578e674d0d470d8c1ee3b33\" args=\"(sp_track *track)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\">bool sp_track_is_placeholder </td>\n          <td>(</td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__types.html#ga47bbd2262f0c8b5d7147af7d62198e48\">sp_track</a> *&nbsp;</td>\n          <td class=\"paramname\"> <em>track</em></td>\n          <td>&nbsp;)&nbsp;</td>\n          <td></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Return true if the track is a placeholder. Placeholder tracks are used to store other objects than tracks in the playlist. Currently this is used in the inbox to store artists, albums and playlists.</p>\n<p>Use <a class=\"el\" href=\"group__link.html#ga82c29419ce70e2b504670e3d45167d5d\">sp_link_create_from_track()</a> to get a link object that points to the real object this \"track\" points to.</p>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>track</em>&nbsp;</td><td>The track</td></tr>\n  </table>\n  </dd>\n</dl>\n<dl class=\"return\"><dt><b>Returns:</b></dt><dd>True if track is a placeholder</dd></dl>\n<dl class=\"note\"><dt><b>Note:</b></dt><dd>Contrary to most functions the track does not have to be loaded for this function to return correct value </dd></dl>\n\n</div>\n</div>\n<a class=\"anchor\" id=\"gab17d380ac941e102af0f308ad885b3c3\"></a><!-- doxytag: member=\"api.h::sp_track_is_starred\" ref=\"gab17d380ac941e102af0f308ad885b3c3\" args=\"(sp_session *session, sp_track *track)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\">bool sp_track_is_starred </td>\n          <td>(</td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__types.html#ga70dd19c6f824cf6a159575aa4c128b53\">sp_session</a> *&nbsp;</td>\n          <td class=\"paramname\"> <em>session</em>, </td>\n        </tr>\n        <tr>\n          <td class=\"paramkey\"></td>\n          <td></td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__types.html#ga47bbd2262f0c8b5d7147af7d62198e48\">sp_track</a> *&nbsp;</td>\n          <td class=\"paramname\"> <em>track</em></td><td>&nbsp;</td>\n        </tr>\n        <tr>\n          <td></td>\n          <td>)</td>\n          <td></td><td></td><td></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Return true if the track is starred by the currently logged in user.</p>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>session</em>&nbsp;</td><td>Session </td></tr>\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>track</em>&nbsp;</td><td>The track</td></tr>\n  </table>\n  </dd>\n</dl>\n<dl class=\"return\"><dt><b>Returns:</b></dt><dd>True if track is starred.</dd></dl>\n<dl class=\"note\"><dt><b>Note:</b></dt><dd>The track must be loaded or this function will always return false. </dd></dl>\n<dl class=\"see\"><dt><b>See also:</b></dt><dd><a class=\"el\" href=\"group__track.html#ga8b69cf193679c7e00031ae43e61c6a54\">sp_track_is_loaded()</a> </dd></dl>\n<dl><dt><b>Examples: </b></dt><dd><a class=\"el\" href=\"browse_8c-example.html#a2\">browse.c</a>.</dd>\n</dl>\n</div>\n</div>\n<a class=\"anchor\" id=\"ga8eb423d3cc2cbfb743c7f23ffb8d0fad\"></a><!-- doxytag: member=\"api.h::sp_track_name\" ref=\"ga8eb423d3cc2cbfb743c7f23ffb8d0fad\" args=\"(sp_track *track)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\">const char* sp_track_name </td>\n          <td>(</td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__types.html#ga47bbd2262f0c8b5d7147af7d62198e48\">sp_track</a> *&nbsp;</td>\n          <td class=\"paramname\"> <em>track</em></td>\n          <td>&nbsp;)&nbsp;</td>\n          <td></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>The string representation of the specified track's name</p>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>track</em>&nbsp;</td><td>A track object</td></tr>\n  </table>\n  </dd>\n</dl>\n<dl class=\"return\"><dt><b>Returns:</b></dt><dd>The string representation of the specified track's name. Returned string is valid as long as the album object stays allocated and no longer than the next call to <a class=\"el\" href=\"group__session.html#gaff27cb730db6debf55e750e39e7fadd7\">sp_session_process_events()</a> If no metadata is available for the track yet, this function returns empty string. </dd></dl>\n<dl><dt><b>Examples: </b></dt><dd><a class=\"el\" href=\"browse_8c-example.html#a3\">browse.c</a>, and <a class=\"el\" href=\"jukebox_8c-example.html#a5\">jukebox.c</a>.</dd>\n</dl>\n</div>\n</div>\n<a class=\"anchor\" id=\"ga0aa945fc43e35d36cc334a52735d83b2\"></a><!-- doxytag: member=\"api.h::sp_track_num_artists\" ref=\"ga0aa945fc43e35d36cc334a52735d83b2\" args=\"(sp_track *track)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\">int sp_track_num_artists </td>\n          <td>(</td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__types.html#ga47bbd2262f0c8b5d7147af7d62198e48\">sp_track</a> *&nbsp;</td>\n          <td class=\"paramname\"> <em>track</em></td>\n          <td>&nbsp;)&nbsp;</td>\n          <td></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>The number of artists performing on the specified track</p>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>track</em>&nbsp;</td><td>The track whose number of participating artists you are interested in</td></tr>\n  </table>\n  </dd>\n</dl>\n<dl class=\"return\"><dt><b>Returns:</b></dt><dd>The number of artists performing on the specified track. If no metadata is available for the track yet, this function returns 0. </dd></dl>\n<dl><dt><b>Examples: </b></dt><dd><a class=\"el\" href=\"browse_8c-example.html#a4\">browse.c</a>.</dd>\n</dl>\n</div>\n</div>\n<a class=\"anchor\" id=\"ga281e0ad4373579c5d24202ea1f93fe7b\"></a><!-- doxytag: member=\"api.h::sp_track_offline_get_status\" ref=\"ga281e0ad4373579c5d24202ea1f93fe7b\" args=\"(sp_track *track)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\"><a class=\"el\" href=\"group__session.html#gaeaa41aad3c0047409996a6ec3b03203f\">sp_track_offline_status</a> sp_track_offline_get_status </td>\n          <td>(</td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__types.html#ga47bbd2262f0c8b5d7147af7d62198e48\">sp_track</a> *&nbsp;</td>\n          <td class=\"paramname\"> <em>track</em></td>\n          <td>&nbsp;)&nbsp;</td>\n          <td></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Return offline status for a track. <a class=\"el\" href=\"structsp__session__callbacks.html#a09912988f00ea5e90835681b382a18fc\">sp_session_callbacks::metadata_updated()</a> will be invoked when offline status of a track changes</p>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>track</em>&nbsp;</td><td>The track</td></tr>\n  </table>\n  </dd>\n</dl>\n<dl class=\"return\"><dt><b>Returns:</b></dt><dd>Stats as described by <a class=\"el\" href=\"group__session.html#gae689044941537050de641a1dcd4c75d5\">sp_track_offline_status</a> </dd></dl>\n\n</div>\n</div>\n<a class=\"anchor\" id=\"ga4570f08f968edbff519b44d2241d2255\"></a><!-- doxytag: member=\"api.h::sp_track_popularity\" ref=\"ga4570f08f968edbff519b44d2241d2255\" args=\"(sp_track *track)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\">int sp_track_popularity </td>\n          <td>(</td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__types.html#ga47bbd2262f0c8b5d7147af7d62198e48\">sp_track</a> *&nbsp;</td>\n          <td class=\"paramname\"> <em>track</em></td>\n          <td>&nbsp;)&nbsp;</td>\n          <td></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Returns popularity for track</p>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>track</em>&nbsp;</td><td>A track object</td></tr>\n  </table>\n  </dd>\n</dl>\n<dl class=\"return\"><dt><b>Returns:</b></dt><dd>Popularity in range 0 to 100, 0 if undefined. If no metadata is available for the track yet, this function returns 0. </dd></dl>\n<dl><dt><b>Examples: </b></dt><dd><a class=\"el\" href=\"browse_8c-example.html#a5\">browse.c</a>.</dd>\n</dl>\n</div>\n</div>\n<a class=\"anchor\" id=\"gaa11098d82e6c2ae42fc2ea1486e741de\"></a><!-- doxytag: member=\"api.h::sp_track_release\" ref=\"gaa11098d82e6c2ae42fc2ea1486e741de\" args=\"(sp_track *track)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\"><a class=\"el\" href=\"group__error.html#gafd27986ce4cd9eeaeca8adda83c9eb6b\">sp_error</a> sp_track_release </td>\n          <td>(</td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__types.html#ga47bbd2262f0c8b5d7147af7d62198e48\">sp_track</a> *&nbsp;</td>\n          <td class=\"paramname\"> <em>track</em></td>\n          <td>&nbsp;)&nbsp;</td>\n          <td></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Decrease the reference count of a track</p>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>track</em>&nbsp;</td><td>The track object </td></tr>\n  </table>\n  </dd>\n</dl>\n<dl class=\"return\"><dt><b>Returns:</b></dt><dd>One of the following errors, from <a class=\"el\" href=\"group__error.html#ga83154178d3a32668658734d2facfa22b\">sp_error</a> SP_ERROR_OK </dd></dl>\n<dl><dt><b>Examples: </b></dt><dd><a class=\"el\" href=\"browse_8c-example.html#a36\">browse.c</a>.</dd>\n</dl>\n</div>\n</div>\n<a class=\"anchor\" id=\"ga34b5a712fb2c683402ff78df73e7545c\"></a><!-- doxytag: member=\"api.h::sp_track_set_starred\" ref=\"ga34b5a712fb2c683402ff78df73e7545c\" args=\"(sp_session *session, sp_track *const *tracks, int num_tracks, bool star)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\"><a class=\"el\" href=\"group__error.html#gafd27986ce4cd9eeaeca8adda83c9eb6b\">sp_error</a> sp_track_set_starred </td>\n          <td>(</td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__types.html#ga70dd19c6f824cf6a159575aa4c128b53\">sp_session</a> *&nbsp;</td>\n          <td class=\"paramname\"> <em>session</em>, </td>\n        </tr>\n        <tr>\n          <td class=\"paramkey\"></td>\n          <td></td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__types.html#ga47bbd2262f0c8b5d7147af7d62198e48\">sp_track</a> *const *&nbsp;</td>\n          <td class=\"paramname\"> <em>tracks</em>, </td>\n        </tr>\n        <tr>\n          <td class=\"paramkey\"></td>\n          <td></td>\n          <td class=\"paramtype\">int&nbsp;</td>\n          <td class=\"paramname\"> <em>num_tracks</em>, </td>\n        </tr>\n        <tr>\n          <td class=\"paramkey\"></td>\n          <td></td>\n          <td class=\"paramtype\">bool&nbsp;</td>\n          <td class=\"paramname\"> <em>star</em></td><td>&nbsp;</td>\n        </tr>\n        <tr>\n          <td></td>\n          <td>)</td>\n          <td></td><td></td><td></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Star/Unstar the specified track</p>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>session</em>&nbsp;</td><td>Session </td></tr>\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>tracks</em>&nbsp;</td><td>Array of pointer to tracks. </td></tr>\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>num_tracks</em>&nbsp;</td><td>Length of <code>tracks</code> array </td></tr>\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>star</em>&nbsp;</td><td>Starred status of the track</td></tr>\n  </table>\n  </dd>\n</dl>\n<dl class=\"note\"><dt><b>Note:</b></dt><dd>This will fail silently if playlists are disabled. </dd></dl>\n<dl class=\"see\"><dt><b>See also:</b></dt><dd>sp_set_playlists_enabled() </dd></dl>\n\n</div>\n</div>\n</div>\n<hr size=\"1\"><address style=\"text-align: right;\"><small>\nGenerated on Wed Jun 13 2012 14:22:40.<br>\nCopyright &copy; 2006&ndash;2012 Spotify Ltd</small></address>\n</body>\n</html>\n"
  },
  {
    "path": "libspotify/docs/html/group__types.html",
    "content": "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\n<html xmlns=\"http://www.w3.org/1999/xhtml\">\n<head>\n<meta http-equiv=\"Content-Type\" content=\"text/xhtml;charset=UTF-8\"/>\n<title>libspotify: Spotify types &amp; structs</title>\n<link href=\"tabs.css\" rel=\"stylesheet\" type=\"text/css\"/>\n<link href=\"doxygen.css\" rel=\"stylesheet\" type=\"text/css\"/>\n</head>\n<body>\n<!-- Generated by Doxygen 1.7.1 -->\n<div class=\"navigation\" id=\"top\">\n  <div class=\"tabs\">\n    <ul class=\"tablist\">\n      <li><a href=\"index.html\"><span>Main&nbsp;Page</span></a></li>\n      <li><a href=\"modules.html\"><span>Modules</span></a></li>\n      <li><a href=\"annotated.html\"><span>Data&nbsp;Structures</span></a></li>\n      <li><a href=\"files.html\"><span>Files</span></a></li>\n      <li><a href=\"examples.html\"><span>Examples</span></a></li>\n    </ul>\n  </div>\n</div>\n<div class=\"header\">\n  <div class=\"summary\">\n<a href=\"#typedef-members\">Typedefs</a>  </div>\n  <div class=\"headertitle\">\n<h1>Spotify types &amp; structs</h1>  </div>\n</div>\n<div class=\"contents\">\n<table class=\"memberdecls\">\n<tr><td colspan=\"2\"><h2><a name=\"typedef-members\"></a>\nTypedefs</h2></td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"anchor\" id=\"ga70dd19c6f824cf6a159575aa4c128b53\"></a><!-- doxytag: member=\"types::sp_session\" ref=\"ga70dd19c6f824cf6a159575aa4c128b53\" args=\"\" -->\ntypedef struct <a class=\"el\" href=\"group__types.html#ga70dd19c6f824cf6a159575aa4c128b53\">sp_session</a>&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__types.html#ga70dd19c6f824cf6a159575aa4c128b53\">sp_session</a></td></tr>\n<tr><td class=\"mdescLeft\">&nbsp;</td><td class=\"mdescRight\">Representation of a session. <br/></td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"anchor\" id=\"ga47bbd2262f0c8b5d7147af7d62198e48\"></a><!-- doxytag: member=\"types::sp_track\" ref=\"ga47bbd2262f0c8b5d7147af7d62198e48\" args=\"\" -->\ntypedef struct <a class=\"el\" href=\"group__types.html#ga47bbd2262f0c8b5d7147af7d62198e48\">sp_track</a>&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__types.html#ga47bbd2262f0c8b5d7147af7d62198e48\">sp_track</a></td></tr>\n<tr><td class=\"mdescLeft\">&nbsp;</td><td class=\"mdescRight\">A track handle. <br/></td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"anchor\" id=\"ga6fd3e5de729c429fef3ff18ece6dcfad\"></a><!-- doxytag: member=\"types::sp_album\" ref=\"ga6fd3e5de729c429fef3ff18ece6dcfad\" args=\"\" -->\ntypedef struct <a class=\"el\" href=\"group__types.html#ga6fd3e5de729c429fef3ff18ece6dcfad\">sp_album</a>&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__types.html#ga6fd3e5de729c429fef3ff18ece6dcfad\">sp_album</a></td></tr>\n<tr><td class=\"mdescLeft\">&nbsp;</td><td class=\"mdescRight\">An album handle. <br/></td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"anchor\" id=\"ga31764fbd69618c10be173c6c03d4c1bc\"></a><!-- doxytag: member=\"types::sp_artist\" ref=\"ga31764fbd69618c10be173c6c03d4c1bc\" args=\"\" -->\ntypedef struct <a class=\"el\" href=\"group__types.html#ga31764fbd69618c10be173c6c03d4c1bc\">sp_artist</a>&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__types.html#ga31764fbd69618c10be173c6c03d4c1bc\">sp_artist</a></td></tr>\n<tr><td class=\"mdescLeft\">&nbsp;</td><td class=\"mdescRight\">An artist handle. <br/></td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"anchor\" id=\"gafd3d5aae485f1012ec91b7948e6f9f2b\"></a><!-- doxytag: member=\"types::sp_artistbrowse\" ref=\"gafd3d5aae485f1012ec91b7948e6f9f2b\" args=\"\" -->\ntypedef struct <a class=\"el\" href=\"group__types.html#gafd3d5aae485f1012ec91b7948e6f9f2b\">sp_artistbrowse</a>&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__types.html#gafd3d5aae485f1012ec91b7948e6f9f2b\">sp_artistbrowse</a></td></tr>\n<tr><td class=\"mdescLeft\">&nbsp;</td><td class=\"mdescRight\">A handle to an artist browse result. <br/></td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"anchor\" id=\"ga9c4550473a7a07790778ba870c31b4d9\"></a><!-- doxytag: member=\"types::sp_albumbrowse\" ref=\"ga9c4550473a7a07790778ba870c31b4d9\" args=\"\" -->\ntypedef struct <a class=\"el\" href=\"group__types.html#ga9c4550473a7a07790778ba870c31b4d9\">sp_albumbrowse</a>&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__types.html#ga9c4550473a7a07790778ba870c31b4d9\">sp_albumbrowse</a></td></tr>\n<tr><td class=\"mdescLeft\">&nbsp;</td><td class=\"mdescRight\">A handle to an album browse result. <br/></td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"anchor\" id=\"ga723de429cd073bcf5d13fb4e0f466ffd\"></a><!-- doxytag: member=\"types::sp_toplistbrowse\" ref=\"ga723de429cd073bcf5d13fb4e0f466ffd\" args=\"\" -->\ntypedef struct <a class=\"el\" href=\"group__types.html#ga723de429cd073bcf5d13fb4e0f466ffd\">sp_toplistbrowse</a>&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__types.html#ga723de429cd073bcf5d13fb4e0f466ffd\">sp_toplistbrowse</a></td></tr>\n<tr><td class=\"mdescLeft\">&nbsp;</td><td class=\"mdescRight\">A handle to a toplist browse result. <br/></td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"anchor\" id=\"gac95893a6b23d4b19f6f149eed6ead1fd\"></a><!-- doxytag: member=\"types::sp_search\" ref=\"gac95893a6b23d4b19f6f149eed6ead1fd\" args=\"\" -->\ntypedef struct <a class=\"el\" href=\"group__types.html#gac95893a6b23d4b19f6f149eed6ead1fd\">sp_search</a>&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__types.html#gac95893a6b23d4b19f6f149eed6ead1fd\">sp_search</a></td></tr>\n<tr><td class=\"mdescLeft\">&nbsp;</td><td class=\"mdescRight\">A handle to a search result. <br/></td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"anchor\" id=\"gaf90a23d6b662c96d52ac19f7f4bc1e39\"></a><!-- doxytag: member=\"types::sp_link\" ref=\"gaf90a23d6b662c96d52ac19f7f4bc1e39\" args=\"\" -->\ntypedef struct <a class=\"el\" href=\"group__types.html#gaf90a23d6b662c96d52ac19f7f4bc1e39\">sp_link</a>&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__types.html#gaf90a23d6b662c96d52ac19f7f4bc1e39\">sp_link</a></td></tr>\n<tr><td class=\"mdescLeft\">&nbsp;</td><td class=\"mdescRight\">A handle to the libspotify internal representation of a URI. <br/></td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"anchor\" id=\"ga61155ca7b1ba941e15490e417441917b\"></a><!-- doxytag: member=\"types::sp_image\" ref=\"ga61155ca7b1ba941e15490e417441917b\" args=\"\" -->\ntypedef struct <a class=\"el\" href=\"group__types.html#ga61155ca7b1ba941e15490e417441917b\">sp_image</a>&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__types.html#ga61155ca7b1ba941e15490e417441917b\">sp_image</a></td></tr>\n<tr><td class=\"mdescLeft\">&nbsp;</td><td class=\"mdescRight\">A handle to an image. <br/></td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"anchor\" id=\"gaed2dbaa1eebd6752f76613daad9158bc\"></a><!-- doxytag: member=\"types::sp_user\" ref=\"gaed2dbaa1eebd6752f76613daad9158bc\" args=\"\" -->\ntypedef struct <a class=\"el\" href=\"group__types.html#gaed2dbaa1eebd6752f76613daad9158bc\">sp_user</a>&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__types.html#gaed2dbaa1eebd6752f76613daad9158bc\">sp_user</a></td></tr>\n<tr><td class=\"mdescLeft\">&nbsp;</td><td class=\"mdescRight\">A handle to a user. <br/></td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"anchor\" id=\"ga1bcf54cbc117a20ab2c15e59eb3a8174\"></a><!-- doxytag: member=\"types::sp_playlist\" ref=\"ga1bcf54cbc117a20ab2c15e59eb3a8174\" args=\"\" -->\ntypedef struct <a class=\"el\" href=\"group__types.html#ga1bcf54cbc117a20ab2c15e59eb3a8174\">sp_playlist</a>&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__types.html#ga1bcf54cbc117a20ab2c15e59eb3a8174\">sp_playlist</a></td></tr>\n<tr><td class=\"mdescLeft\">&nbsp;</td><td class=\"mdescRight\">A playlist handle. <br/></td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"anchor\" id=\"ga45a2febbe167483e48dab8d606d462d7\"></a><!-- doxytag: member=\"types::sp_playlistcontainer\" ref=\"ga45a2febbe167483e48dab8d606d462d7\" args=\"\" -->\ntypedef struct <a class=\"el\" href=\"group__types.html#ga45a2febbe167483e48dab8d606d462d7\">sp_playlistcontainer</a>&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__types.html#ga45a2febbe167483e48dab8d606d462d7\">sp_playlistcontainer</a></td></tr>\n<tr><td class=\"mdescLeft\">&nbsp;</td><td class=\"mdescRight\">A playlist container (playlist containing other playlists) handle. <br/></td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"anchor\" id=\"gaec0f2e5098cebc05ce56adfc9b346510\"></a><!-- doxytag: member=\"types::sp_inbox\" ref=\"gaec0f2e5098cebc05ce56adfc9b346510\" args=\"\" -->\ntypedef struct <a class=\"el\" href=\"group__types.html#gaec0f2e5098cebc05ce56adfc9b346510\">sp_inbox</a>&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__types.html#gaec0f2e5098cebc05ce56adfc9b346510\">sp_inbox</a></td></tr>\n<tr><td class=\"mdescLeft\">&nbsp;</td><td class=\"mdescRight\">Add to inbox request handle. <br/></td></tr>\n</table>\n</div>\n<hr size=\"1\"><address style=\"text-align: right;\"><small>\nGenerated on Wed Jun 13 2012 14:22:40.<br>\nCopyright &copy; 2006&ndash;2012 Spotify Ltd</small></address>\n</body>\n</html>\n"
  },
  {
    "path": "libspotify/docs/html/group__user.html",
    "content": "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\n<html xmlns=\"http://www.w3.org/1999/xhtml\">\n<head>\n<meta http-equiv=\"Content-Type\" content=\"text/xhtml;charset=UTF-8\"/>\n<title>libspotify: User handling</title>\n<link href=\"tabs.css\" rel=\"stylesheet\" type=\"text/css\"/>\n<link href=\"doxygen.css\" rel=\"stylesheet\" type=\"text/css\"/>\n</head>\n<body>\n<!-- Generated by Doxygen 1.7.1 -->\n<div class=\"navigation\" id=\"top\">\n  <div class=\"tabs\">\n    <ul class=\"tablist\">\n      <li><a href=\"index.html\"><span>Main&nbsp;Page</span></a></li>\n      <li><a href=\"modules.html\"><span>Modules</span></a></li>\n      <li><a href=\"annotated.html\"><span>Data&nbsp;Structures</span></a></li>\n      <li><a href=\"files.html\"><span>Files</span></a></li>\n      <li><a href=\"examples.html\"><span>Examples</span></a></li>\n    </ul>\n  </div>\n</div>\n<div class=\"header\">\n  <div class=\"summary\">\n<a href=\"#typedef-members\">Typedefs</a> &#124;\n<a href=\"#enum-members\">Enumerations</a> &#124;\n<a href=\"#func-members\">Functions</a>  </div>\n  <div class=\"headertitle\">\n<h1>User handling</h1>  </div>\n</div>\n<div class=\"contents\">\n<table class=\"memberdecls\">\n<tr><td colspan=\"2\"><h2><a name=\"typedef-members\"></a>\nTypedefs</h2></td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">typedef enum <a class=\"el\" href=\"group__user.html#ga6af84143c0622b6fc5539bb1ae111e5b\">sp_relation_type</a>&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__user.html#ga3a5dbf9aee629d8a9b43dfb24881a9b4\">sp_relation_type</a></td></tr>\n<tr><td colspan=\"2\"><h2><a name=\"enum-members\"></a>\nEnumerations</h2></td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">enum &nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__user.html#ga6af84143c0622b6fc5539bb1ae111e5b\">sp_relation_type</a> { <br/>\n&nbsp;&nbsp;<a class=\"el\" href=\"group__user.html#gga6af84143c0622b6fc5539bb1ae111e5ba18f24164eef0e687b351c2aa6753e35e\">SP_RELATION_TYPE_UNKNOWN</a> =  0, \n<br/>\n&nbsp;&nbsp;<a class=\"el\" href=\"group__user.html#gga6af84143c0622b6fc5539bb1ae111e5bad9805f100828a9d3b64c3cc66f2ac5c1\">SP_RELATION_TYPE_NONE</a> =  1, \n<br/>\n&nbsp;&nbsp;<a class=\"el\" href=\"group__user.html#gga6af84143c0622b6fc5539bb1ae111e5ba06b2f38745c467e7e362c7744cb74205\">SP_RELATION_TYPE_UNIDIRECTIONAL</a> =  2, \n<br/>\n&nbsp;&nbsp;<a class=\"el\" href=\"group__user.html#gga6af84143c0622b6fc5539bb1ae111e5ba4bfef63cabd016cf1e6b11347a05d389\">SP_RELATION_TYPE_BIDIRECTIONAL</a> =  3\n<br/>\n }</td></tr>\n<tr><td colspan=\"2\"><h2><a name=\"func-members\"></a>\nFunctions</h2></td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">const char *&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__user.html#gad9ac5456cd129c31d2c577ba14e88f8c\">sp_user_canonical_name</a> (<a class=\"el\" href=\"group__types.html#gaed2dbaa1eebd6752f76613daad9158bc\">sp_user</a> *user)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">const char *&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__user.html#ga0052befb81a93bb7106ca863de892610\">sp_user_display_name</a> (<a class=\"el\" href=\"group__types.html#gaed2dbaa1eebd6752f76613daad9158bc\">sp_user</a> *user)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">bool&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__user.html#ga0996fb9814564e4ad39b8a500cb3de21\">sp_user_is_loaded</a> (<a class=\"el\" href=\"group__types.html#gaed2dbaa1eebd6752f76613daad9158bc\">sp_user</a> *user)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__error.html#gafd27986ce4cd9eeaeca8adda83c9eb6b\">sp_error</a>&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__user.html#ga232816a3c8f42ef2663b8d99261f2dae\">sp_user_add_ref</a> (<a class=\"el\" href=\"group__types.html#gaed2dbaa1eebd6752f76613daad9158bc\">sp_user</a> *user)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"el\" href=\"group__error.html#gafd27986ce4cd9eeaeca8adda83c9eb6b\">sp_error</a>&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"group__user.html#gab1ffba4355073e1f72594c9e1b22ebb4\">sp_user_release</a> (<a class=\"el\" href=\"group__types.html#gaed2dbaa1eebd6752f76613daad9158bc\">sp_user</a> *user)</td></tr>\n</table>\n<hr/><h2>Typedef Documentation</h2>\n<a class=\"anchor\" id=\"ga3a5dbf9aee629d8a9b43dfb24881a9b4\"></a><!-- doxytag: member=\"api.h::sp_relation_type\" ref=\"ga3a5dbf9aee629d8a9b43dfb24881a9b4\" args=\"\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\">typedef enum <a class=\"el\" href=\"group__user.html#ga6af84143c0622b6fc5539bb1ae111e5b\">sp_relation_type</a>  <a class=\"el\" href=\"group__user.html#ga6af84143c0622b6fc5539bb1ae111e5b\">sp_relation_type</a></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>User relation type </p>\n\n</div>\n</div>\n<hr/><h2>Enumeration Type Documentation</h2>\n<a class=\"anchor\" id=\"ga6af84143c0622b6fc5539bb1ae111e5b\"></a><!-- doxytag: member=\"api.h::sp_relation_type\" ref=\"ga6af84143c0622b6fc5539bb1ae111e5b\" args=\"\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\">enum <a class=\"el\" href=\"group__user.html#ga6af84143c0622b6fc5539bb1ae111e5b\">sp_relation_type</a></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>User relation type </p>\n<dl><dt><b>Enumerator: </b></dt><dd><table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n<tr><td valign=\"top\"><em><a class=\"anchor\" id=\"gga6af84143c0622b6fc5539bb1ae111e5ba18f24164eef0e687b351c2aa6753e35e\"></a><!-- doxytag: member=\"SP_RELATION_TYPE_UNKNOWN\" ref=\"gga6af84143c0622b6fc5539bb1ae111e5ba18f24164eef0e687b351c2aa6753e35e\" args=\"\" -->SP_RELATION_TYPE_UNKNOWN</em>&nbsp;</td><td>\n<p>Not yet known. </p>\n</td></tr>\n<tr><td valign=\"top\"><em><a class=\"anchor\" id=\"gga6af84143c0622b6fc5539bb1ae111e5bad9805f100828a9d3b64c3cc66f2ac5c1\"></a><!-- doxytag: member=\"SP_RELATION_TYPE_NONE\" ref=\"gga6af84143c0622b6fc5539bb1ae111e5bad9805f100828a9d3b64c3cc66f2ac5c1\" args=\"\" -->SP_RELATION_TYPE_NONE</em>&nbsp;</td><td>\n<p>No relation. </p>\n</td></tr>\n<tr><td valign=\"top\"><em><a class=\"anchor\" id=\"gga6af84143c0622b6fc5539bb1ae111e5ba06b2f38745c467e7e362c7744cb74205\"></a><!-- doxytag: member=\"SP_RELATION_TYPE_UNIDIRECTIONAL\" ref=\"gga6af84143c0622b6fc5539bb1ae111e5ba06b2f38745c467e7e362c7744cb74205\" args=\"\" -->SP_RELATION_TYPE_UNIDIRECTIONAL</em>&nbsp;</td><td>\n<p>The currently logged in user is following this uer. </p>\n</td></tr>\n<tr><td valign=\"top\"><em><a class=\"anchor\" id=\"gga6af84143c0622b6fc5539bb1ae111e5ba4bfef63cabd016cf1e6b11347a05d389\"></a><!-- doxytag: member=\"SP_RELATION_TYPE_BIDIRECTIONAL\" ref=\"gga6af84143c0622b6fc5539bb1ae111e5ba4bfef63cabd016cf1e6b11347a05d389\" args=\"\" -->SP_RELATION_TYPE_BIDIRECTIONAL</em>&nbsp;</td><td>\n<p>Bidirectional friendship established. </p>\n</td></tr>\n</table>\n</dd>\n</dl>\n\n</div>\n</div>\n<hr/><h2>Function Documentation</h2>\n<a class=\"anchor\" id=\"ga232816a3c8f42ef2663b8d99261f2dae\"></a><!-- doxytag: member=\"api.h::sp_user_add_ref\" ref=\"ga232816a3c8f42ef2663b8d99261f2dae\" args=\"(sp_user *user)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\"><a class=\"el\" href=\"group__error.html#gafd27986ce4cd9eeaeca8adda83c9eb6b\">sp_error</a> sp_user_add_ref </td>\n          <td>(</td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__types.html#gaed2dbaa1eebd6752f76613daad9158bc\">sp_user</a> *&nbsp;</td>\n          <td class=\"paramname\"> <em>user</em></td>\n          <td>&nbsp;)&nbsp;</td>\n          <td></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Increase the reference count of an user</p>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>user</em>&nbsp;</td><td>The user object </td></tr>\n  </table>\n  </dd>\n</dl>\n<dl class=\"return\"><dt><b>Returns:</b></dt><dd>One of the following errors, from <a class=\"el\" href=\"group__error.html#ga83154178d3a32668658734d2facfa22b\">sp_error</a> SP_ERROR_OK </dd></dl>\n\n</div>\n</div>\n<a class=\"anchor\" id=\"gad9ac5456cd129c31d2c577ba14e88f8c\"></a><!-- doxytag: member=\"api.h::sp_user_canonical_name\" ref=\"gad9ac5456cd129c31d2c577ba14e88f8c\" args=\"(sp_user *user)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\">const char* sp_user_canonical_name </td>\n          <td>(</td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__types.html#gaed2dbaa1eebd6752f76613daad9158bc\">sp_user</a> *&nbsp;</td>\n          <td class=\"paramname\"> <em>user</em></td>\n          <td>&nbsp;)&nbsp;</td>\n          <td></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Get a pointer to a string representing the user's canonical username.</p>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>user</em>&nbsp;</td><td>The Spotify user whose canonical username you would like a string representation of</td></tr>\n  </table>\n  </dd>\n</dl>\n<dl class=\"return\"><dt><b>Returns:</b></dt><dd>A string representing the canonical username. </dd></dl>\n\n</div>\n</div>\n<a class=\"anchor\" id=\"ga0052befb81a93bb7106ca863de892610\"></a><!-- doxytag: member=\"api.h::sp_user_display_name\" ref=\"ga0052befb81a93bb7106ca863de892610\" args=\"(sp_user *user)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\">const char* sp_user_display_name </td>\n          <td>(</td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__types.html#gaed2dbaa1eebd6752f76613daad9158bc\">sp_user</a> *&nbsp;</td>\n          <td class=\"paramname\"> <em>user</em></td>\n          <td>&nbsp;)&nbsp;</td>\n          <td></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Get a pointer to a string representing the user's displayable username. If there is no difference between the canonical username and the display name, or if the library does not know about the display name yet, the canonical username will be returned.</p>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>user</em>&nbsp;</td><td>The Spotify user whose displayable username you would like a string representation of</td></tr>\n  </table>\n  </dd>\n</dl>\n<dl class=\"return\"><dt><b>Returns:</b></dt><dd>A string </dd></dl>\n\n</div>\n</div>\n<a class=\"anchor\" id=\"ga0996fb9814564e4ad39b8a500cb3de21\"></a><!-- doxytag: member=\"api.h::sp_user_is_loaded\" ref=\"ga0996fb9814564e4ad39b8a500cb3de21\" args=\"(sp_user *user)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\">bool sp_user_is_loaded </td>\n          <td>(</td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__types.html#gaed2dbaa1eebd6752f76613daad9158bc\">sp_user</a> *&nbsp;</td>\n          <td class=\"paramname\"> <em>user</em></td>\n          <td>&nbsp;)&nbsp;</td>\n          <td></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Get load status for a user object. Before it is loaded, only the user's canonical username is known.</p>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>user</em>&nbsp;</td><td>Spotify user object</td></tr>\n  </table>\n  </dd>\n</dl>\n<dl class=\"return\"><dt><b>Returns:</b></dt><dd>True if user object is loaded, otherwise false </dd></dl>\n\n</div>\n</div>\n<a class=\"anchor\" id=\"gab1ffba4355073e1f72594c9e1b22ebb4\"></a><!-- doxytag: member=\"api.h::sp_user_release\" ref=\"gab1ffba4355073e1f72594c9e1b22ebb4\" args=\"(sp_user *user)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\"><a class=\"el\" href=\"group__error.html#gafd27986ce4cd9eeaeca8adda83c9eb6b\">sp_error</a> sp_user_release </td>\n          <td>(</td>\n          <td class=\"paramtype\"><a class=\"el\" href=\"group__types.html#gaed2dbaa1eebd6752f76613daad9158bc\">sp_user</a> *&nbsp;</td>\n          <td class=\"paramname\"> <em>user</em></td>\n          <td>&nbsp;)&nbsp;</td>\n          <td></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Decrease the reference count of an user</p>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>user</em>&nbsp;</td><td>The user object </td></tr>\n  </table>\n  </dd>\n</dl>\n<dl class=\"return\"><dt><b>Returns:</b></dt><dd>One of the following errors, from <a class=\"el\" href=\"group__error.html#ga83154178d3a32668658734d2facfa22b\">sp_error</a> SP_ERROR_OK </dd></dl>\n\n</div>\n</div>\n</div>\n<hr size=\"1\"><address style=\"text-align: right;\"><small>\nGenerated on Wed Jun 13 2012 14:22:40.<br>\nCopyright &copy; 2006&ndash;2012 Spotify Ltd</small></address>\n</body>\n</html>\n"
  },
  {
    "path": "libspotify/docs/html/index.html",
    "content": "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\n<html xmlns=\"http://www.w3.org/1999/xhtml\">\n<head>\n<meta http-equiv=\"Content-Type\" content=\"text/xhtml;charset=UTF-8\"/>\n<title>libspotify: libspotify 12.1.51 API Documentation</title>\n<link href=\"tabs.css\" rel=\"stylesheet\" type=\"text/css\"/>\n<link href=\"doxygen.css\" rel=\"stylesheet\" type=\"text/css\"/>\n</head>\n<body>\n<!-- Generated by Doxygen 1.7.1 -->\n<div class=\"navigation\" id=\"top\">\n  <div class=\"tabs\">\n    <ul class=\"tablist\">\n      <li class=\"current\"><a href=\"index.html\"><span>Main&nbsp;Page</span></a></li>\n      <li><a href=\"modules.html\"><span>Modules</span></a></li>\n      <li><a href=\"annotated.html\"><span>Data&nbsp;Structures</span></a></li>\n      <li><a href=\"files.html\"><span>Files</span></a></li>\n      <li><a href=\"examples.html\"><span>Examples</span></a></li>\n    </ul>\n  </div>\n</div>\n<div class=\"header\">\n  <div class=\"headertitle\">\n<h1>libspotify 12.1.51 API Documentation </h1>  </div>\n</div>\n<div class=\"contents\">\n<p>This documentation explains how you can make use of the <em>libspotify</em> C API within an application of your own.</p>\n<p>The documentation was generated with <a href=\"http://www.doxygen.org/\">Doxygen</a>. You will find a list of submodules in the <a href=\"modules.html\">Modules</a> section. The list of modules are ordered in a reasonable reading order. It begins with some <a href=\"group__types.html\">simple types</a> used throughout the rest of the modules, continues with basic <a href=\"group__error.html\">error handling</a> and the functions required to <a href=\"group__session.html\">manage sessions</a>.</p>\n<p>The rest of the modules are specfic parts of <em>libspotify</em> for accessing information about <a href=\"group__artistbrowse.html\">artists</a>, <a href=\"group__albumbrowse.html\">albums</a>, <a href=\"group__track.html\">tracks</a>, and <a href=\"group__playlist.html\">playlists</a>. Separate modules are available to handle <a href=\"group__search.html\">searches</a> and <a href=\"group__image.html\">images</a>.</p>\n<p>This initial chapter of <em>libspotify</em> will focus on the general design of the library, and things to take into consideration once you start working with it.</p>\n<p>For most of the functionality, there are <a href=\"examples.html\">examples</a> available in <code></code>.</p>\n<h2><a class=\"anchor\" id=\"restr_sec\"></a>\nIssues and Restrictions</h2>\n<p>A few restrictions apply to the <em>libspotify</em> library. These may be changed (or fixed) in future versions of the library.</p>\n<ul>\n<li>Only one process can access the cache and settings directory. It is <em>your</em> responsibility to make sure instances of your application, or any other application and your application does not attempt to use the same cache. You can do this using a clever naming schema, or using a lock-file.</li>\n<li>Even though sp_session_init() creates a new object, there are still some global variables behind the scenes that will stop you from creating multiple sessions within a single process.</li>\n</ul>\n<h2><a class=\"anchor\" id=\"general_sec\"></a>\nGeneral Design</h2>\n<p>In this section, you will find the overall philosophy of the library with regard to memory management and error handling.</p>\n<h3><a class=\"anchor\" id=\"err_sec\"></a>\nError Handling</h3>\n<p>All functions that have some form of useful error state returns an <a class=\"el\" href=\"group__error.html#ga83154178d3a32668658734d2facfa22b\">sp_error</a>. The actual result value is returned in an <code>out</code> pointer in these cases. Some functions return pointers where you must check for <code>NULL</code> before using the returned value. Those places should be documented next to each function.</p>\n<p>In addition to functions returning an <a class=\"el\" href=\"group__error.html#ga83154178d3a32668658734d2facfa22b\">sp_error</a>, some request objects (browse and search objects) have an error accessor. When the object has been loaded, the error code will be set to reflect the success or failure of the request.</p>\n<p>A trivial <a class=\"el\" href=\"group__error.html#ga983dee341d3c2008830513b7cffe7bf3\">error code to string mapper function</a> exists that works just like <code>strerror(3)</code>.</p>\n<h3><a class=\"anchor\" id=\"refcnt_sec\"></a>\nReference Counting</h3>\n<p>Reference counting is used for all domain objects in <em>libspotify</em>. Functions including the string <b>create</b> will return an object with a pre-incremented reference count. Thus, each <code>create</code> must have a corresponding <code>release</code> when the value is no longer needed.</p>\n<p>Other accessor functions (including <a class=\"el\" href=\"group__link.html#gab32979d26dcf68936202fa7aed7b6e49\">sp_link_as_artist</a> et al.), on the other hand, returns a reference borrowed from the object it was retrieved from. Retrieving an <a class=\"el\" href=\"group__types.html#ga6fd3e5de729c429fef3ff18ece6dcfad\" title=\"An album handle.\">sp_album</a> from an <a class=\"el\" href=\"group__types.html#gaf90a23d6b662c96d52ac19f7f4bc1e39\" title=\"A handle to the libspotify internal representation of a URI.\">sp_link</a> would make the album object survive until the link object is freed, unless its reference count is explicitly incremented.</p>\n<h3><a class=\"anchor\" id=\"threads_sec\"></a>\nThreads</h3>\n<p>The library itself uses multiple threads internally. To allow for synchronization between these threads, you must implement the sp_session_callbacks::notify_main_thread callback. Whenever called (from some internal thread), the application must wake up the main loop so the <a class=\"el\" href=\"group__session.html#gaff27cb730db6debf55e750e39e7fadd7\">sp_session_process_events()</a> function can be run.</p>\n<p>The API itself is <em>not</em> thread-safe. Thus, you must take care not to call the API functions from more than one of your own threads.</p>\n<h3><a class=\"anchor\" id=\"objects_sec\"></a>\nObjects</h3>\n<p>All objects (tracks, albums, artists, etc) are loaded asynchronously. Therefore the API user must query the object via the _is_loaded() functions to check that the object data has been populated. There is currently no way of finding out when data has been updated for a specific object. Rather, the user need to iterate all objects of interest upon invokation of the metadata_updated() callback.</p>\n<p>Also, objects are not populated when created as a result of a sp_link_as_...() method.</p>\n<h3><a class=\"anchor\" id=\"cache_sec\"></a>\nDisk Cache Management</h3>\n<p>Currently the disk cache can only be opened by one process at a time. It is preferrable not to put the cache in a network file system. To avoid clashes, we recommend you to put set the cache location to <code>/var/tmp/<em>username</em>/<em>appname</em>/</code> and to add some kind of lock. The <em>appname</em> would be a mangled user-agent string.</p>\n<p>While you could simply remove the cache when the application exits to avoid the locking issue, your application will be slower as music, playlists and other metadata will have to be loaded from the server on each login. You are strongly encouraged to use a persistent cache.</p>\n<p>Settings should be stored in the users home directory, but they should also be kept separate per application. We would recommend <code>~/.config/<em>appname</em>/libspotify/</code> for these files on UNIX-like systems or <code>%appdata%\\<em>appname</em>\\libspotify\\</code> on Windows.</p>\n<h2><a class=\"anchor\" id=\"session_sec\"></a>\nSession Management</h2>\n<p>Before running any application you will need an <em>application key</em>. An application key allows Spotify to identify your application and should be unique per application. You will find more information about the application keys on our <a href=\"http://developer.spotify.com/\">developer website</a>. We have choosen not to distribute the example programs with an application key, as that might cause the key to be misused. We encourage you to get a valid application key, and put it in a file called <code>appkey.c</code> and compile the examples using the included makefile.</p>\n<p>In order to ensure all data is correctly synced to disk, we encourage you to actually use <a class=\"el\" href=\"group__session.html#gab7f08ca0939985b30ae2d1ed9db1d726\">sp_session_logout()</a> before terminating your application. Efter logout, you will receive a <a class=\"el\" href=\"structsp__session__callbacks.html#a073231e9ceb3d40f4a772ab64ba4ece7\">callback</a> call in which you could display a login box, or terminate.</p>\n<h2><a class=\"anchor\" id=\"image_sec\"></a>\nImages</h2>\n<p>Images are identified with a <code>const byte*</code> value, returned by various functions in the API (such as <a class=\"el\" href=\"group__album.html#ga6616ef3df724af185c5eb58e8a0fb808\">sp_album_cover()</a>). The pointers are valid until the object is freed, thus you should keep a reference to the objects until you are no longer using the image ID.</p>\n<p>It is also possible to get references to images as URIs (see the sp_link type). This might be favourable if you need to store a reference to an image for later use but want to release the originating object.</p>\n<p>Images will always be given to the application compressed using a image compression format. Currently only JPEG encoded images are delivered. See <a class=\"el\" href=\"group__image.html#ga04448e81ca4916ba7ed223d0d817e803\">sp_image_format()</a>. The API user should use <a class=\"el\" href=\"group__image.html#ga03700a7dfa90bfc8200b89f15acd91aa\">sp_image_data()</a> to get the encoded data and the application need to do the decoding of the image by itself.</p>\n<h2><a class=\"anchor\" id=\"audio_sec\"></a>\nAudio</h2>\n<p>The audio is delivered through a <a class=\"el\" href=\"structsp__session__callbacks.html#a33a31478b8de1882ad7847ad033fbaeb\">push-callback</a> called by <em>libspotify</em> when data is available. Your callback may eat all data, or just enough to fill some constant-sized buffer. The callback will be called from a libspotify internal thread, so if you share state between the audio callback and the main thread, be sure to add adequate thread synchronization.</p>\n<p>Samples are delivered as integers, see <a class=\"el\" href=\"structsp__audioformat.html\">sp_audioformat</a>. One <em>frame</em> consists of the same number of samples as there are channels. I.e. interleaving is on the sample level.</p>\n<h2><a class=\"anchor\" id=\"examples_sec\"></a>\nExamples</h2>\n<p>Included in the distribution are a couple of example files designed to get you started easily.</p>\n<h2><a class=\"anchor\" id=\"license_sec\"></a>\nLicenses</h2>\n<p>The example code distributed with <em>libspotify</em> uses the <a href=\"http://www.opensource.org/licenses/mit-license.php\">MIT license</a>. All documentation, <em>libspotify</em> itself, and the associated C header file are distributed under the libspotify <a href=\"http://developer.spotify.com/en/libspotify/terms-of-use/\">Terms of Use</a>. </p>\n</div>\n<hr size=\"1\"><address style=\"text-align: right;\"><small>\nGenerated on Wed Jun 13 2012 14:22:40.<br>\nCopyright &copy; 2006&ndash;2012 Spotify Ltd</small></address>\n</body>\n</html>\n"
  },
  {
    "path": "libspotify/docs/html/jukebox_8c-example.html",
    "content": "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\n<html xmlns=\"http://www.w3.org/1999/xhtml\">\n<head>\n<meta http-equiv=\"Content-Type\" content=\"text/xhtml;charset=UTF-8\"/>\n<title>libspotify: jukebox.c</title>\n<link href=\"tabs.css\" rel=\"stylesheet\" type=\"text/css\"/>\n<link href=\"doxygen.css\" rel=\"stylesheet\" type=\"text/css\"/>\n</head>\n<body>\n<!-- Generated by Doxygen 1.7.1 -->\n<div class=\"navigation\" id=\"top\">\n  <div class=\"tabs\">\n    <ul class=\"tablist\">\n      <li><a href=\"index.html\"><span>Main&nbsp;Page</span></a></li>\n      <li><a href=\"modules.html\"><span>Modules</span></a></li>\n      <li><a href=\"annotated.html\"><span>Data&nbsp;Structures</span></a></li>\n      <li><a href=\"files.html\"><span>Files</span></a></li>\n      <li><a href=\"examples.html\"><span>Examples</span></a></li>\n    </ul>\n  </div>\n</div>\n<div class=\"header\">\n  <div class=\"headertitle\">\n<h1>jukebox.c</h1>  </div>\n</div>\n<div class=\"contents\">\n<p>The jukebox.c example shows how you can use playback and playlist functions.</p>\n<div class=\"fragment\"><pre class=\"fragment\">\n<span class=\"preprocessor\">#include &lt;errno.h&gt;</span>\n<span class=\"preprocessor\">#include &lt;libgen.h&gt;</span>\n<span class=\"preprocessor\">#include &lt;pthread.h&gt;</span>\n<span class=\"preprocessor\">#include &lt;stdint.h&gt;</span>\n<span class=\"preprocessor\">#include &lt;stdio.h&gt;</span>\n<span class=\"preprocessor\">#include &lt;stdlib.h&gt;</span>\n<span class=\"preprocessor\">#include &lt;string.h&gt;</span>\n<span class=\"preprocessor\">#include &lt;unistd.h&gt;</span>\n<span class=\"preprocessor\">#include &lt;sys/time.h&gt;</span>\n\n<span class=\"preprocessor\">#include &lt;libspotify/api.h&gt;</span>\n\n<span class=\"preprocessor\">#include &quot;audio.h&quot;</span>\n\n\n<span class=\"comment\">/* --- Data --- */</span>\n<span class=\"keyword\">extern</span> <span class=\"keyword\">const</span> uint8_t g_appkey[];\n<span class=\"keyword\">extern</span> <span class=\"keyword\">const</span> <span class=\"keywordtype\">size_t</span> g_appkey_size;\n\n<span class=\"keyword\">static</span> audio_fifo_t g_audiofifo;\n<span class=\"keyword\">static</span> pthread_mutex_t g_notify_mutex;\n<span class=\"keyword\">static</span> pthread_cond_t g_notify_cond;\n<span class=\"keyword\">static</span> <span class=\"keywordtype\">int</span> g_notify_do;\n<span class=\"keyword\">static</span> <span class=\"keywordtype\">int</span> g_playback_done;\n<span class=\"keyword\">static</span> <a class=\"code\" href=\"group__types.html#ga70dd19c6f824cf6a159575aa4c128b53\" title=\"Representation of a session.\">sp_session</a> *g_sess;\n<span class=\"keyword\">static</span> <a class=\"code\" href=\"group__types.html#ga1bcf54cbc117a20ab2c15e59eb3a8174\" title=\"A playlist handle.\">sp_playlist</a> *g_jukeboxlist;\n<span class=\"keyword\">const</span> <span class=\"keywordtype\">char</span> *g_listname;\n<span class=\"keyword\">static</span> <span class=\"keywordtype\">int</span> g_remove_tracks = 0;\n<span class=\"keyword\">static</span> <a class=\"code\" href=\"group__types.html#ga47bbd2262f0c8b5d7147af7d62198e48\" title=\"A track handle.\">sp_track</a> *g_currenttrack;\n<span class=\"keyword\">static</span> <span class=\"keywordtype\">int</span> g_track_index;\n\n\n<span class=\"keyword\">static</span> <span class=\"keywordtype\">void</span> try_jukebox_start(<span class=\"keywordtype\">void</span>)\n{\n    <a class=\"code\" href=\"group__types.html#ga47bbd2262f0c8b5d7147af7d62198e48\" title=\"A track handle.\">sp_track</a> *t;\n\n    <span class=\"keywordflow\">if</span> (!g_jukeboxlist)\n        <span class=\"keywordflow\">return</span>;\n\n    <span class=\"keywordflow\">if</span> (!<a name=\"a0\"></a><a class=\"code\" href=\"group__playlist.html#ga684a3acc60f99b3b26488ed813ee5d23\">sp_playlist_num_tracks</a>(g_jukeboxlist)) {\n        fprintf(stderr, <span class=\"stringliteral\">&quot;jukebox: No tracks in playlist. Waiting\\n&quot;</span>);\n        <span class=\"keywordflow\">return</span>;\n    }\n\n    <span class=\"keywordflow\">if</span> (<a class=\"code\" href=\"group__playlist.html#ga684a3acc60f99b3b26488ed813ee5d23\">sp_playlist_num_tracks</a>(g_jukeboxlist) &lt; g_track_index) {\n        fprintf(stderr, <span class=\"stringliteral\">&quot;jukebox: No more tracks in playlist. Waiting\\n&quot;</span>);\n        <span class=\"keywordflow\">return</span>;\n    }\n\n    t = <a name=\"a1\"></a><a class=\"code\" href=\"group__playlist.html#ga7a03854fe6072476306780d23c6cac16\">sp_playlist_track</a>(g_jukeboxlist, g_track_index);\n\n    <span class=\"keywordflow\">if</span> (g_currenttrack &amp;&amp; t != g_currenttrack) {\n        <span class=\"comment\">/* Someone changed the current track */</span>\n        audio_fifo_flush(&amp;g_audiofifo);\n        <a name=\"a2\"></a><a class=\"code\" href=\"group__session.html#gafa7ee2803f119451bb8be3bf28746975\">sp_session_player_unload</a>(g_sess);\n        g_currenttrack = NULL;\n    }\n\n    <span class=\"keywordflow\">if</span> (!t)\n        <span class=\"keywordflow\">return</span>;\n\n    <span class=\"keywordflow\">if</span> (<a name=\"a3\"></a><a class=\"code\" href=\"group__track.html#ga947c0f7755b0c4955ca0b0993db0f2b5\">sp_track_error</a>(t) != <a name=\"a4\"></a><a class=\"code\" href=\"group__error.html#ggafd27986ce4cd9eeaeca8adda83c9eb6ba16cb277dc84328e4b2c0cf6d5a0c0b8d\" title=\"No errors encountered.\">SP_ERROR_OK</a>)\n        <span class=\"keywordflow\">return</span>;\n\n    <span class=\"keywordflow\">if</span> (g_currenttrack == t)\n        <span class=\"keywordflow\">return</span>;\n\n    g_currenttrack = t;\n\n    printf(<span class=\"stringliteral\">&quot;jukebox: Now playing \\&quot;%s\\&quot;...\\n&quot;</span>, <a name=\"a5\"></a><a class=\"code\" href=\"group__track.html#ga8eb423d3cc2cbfb743c7f23ffb8d0fad\">sp_track_name</a>(t));\n    fflush(stdout);\n\n    <a name=\"a6\"></a><a class=\"code\" href=\"group__session.html#gac73bf2c569a43d824439b557d5e4b293\">sp_session_player_load</a>(g_sess, t);\n    <a name=\"a7\"></a><a class=\"code\" href=\"group__session.html#gab66c5915967e4f90db945b118e620624\">sp_session_player_play</a>(g_sess, 1);\n}\n\n<span class=\"comment\">/* --------------------------  PLAYLIST CALLBACKS  ------------------------- */</span>\n<span class=\"keyword\">static</span> <span class=\"keywordtype\">void</span> tracks_added(<a class=\"code\" href=\"group__types.html#ga1bcf54cbc117a20ab2c15e59eb3a8174\" title=\"A playlist handle.\">sp_playlist</a> *pl, <a class=\"code\" href=\"group__types.html#ga47bbd2262f0c8b5d7147af7d62198e48\" title=\"A track handle.\">sp_track</a> * <span class=\"keyword\">const</span> *tracks,\n                         <span class=\"keywordtype\">int</span> num_tracks, <span class=\"keywordtype\">int</span> position, <span class=\"keywordtype\">void</span> *userdata)\n{\n    <span class=\"keywordflow\">if</span> (pl != g_jukeboxlist)\n        <span class=\"keywordflow\">return</span>;\n\n    printf(<span class=\"stringliteral\">&quot;jukebox: %d tracks were added\\n&quot;</span>, num_tracks);\n    fflush(stdout);\n    try_jukebox_start();\n}\n\n<span class=\"keyword\">static</span> <span class=\"keywordtype\">void</span> tracks_removed(<a class=\"code\" href=\"group__types.html#ga1bcf54cbc117a20ab2c15e59eb3a8174\" title=\"A playlist handle.\">sp_playlist</a> *pl, <span class=\"keyword\">const</span> <span class=\"keywordtype\">int</span> *tracks,\n                           <span class=\"keywordtype\">int</span> num_tracks, <span class=\"keywordtype\">void</span> *userdata)\n{\n    <span class=\"keywordtype\">int</span> i, k = 0;\n\n    <span class=\"keywordflow\">if</span> (pl != g_jukeboxlist)\n        <span class=\"keywordflow\">return</span>;\n\n    <span class=\"keywordflow\">for</span> (i = 0; i &lt; num_tracks; ++i)\n        <span class=\"keywordflow\">if</span> (tracks[i] &lt; g_track_index)\n            ++k;\n\n    g_track_index -= k;\n\n    printf(<span class=\"stringliteral\">&quot;jukebox: %d tracks were removed\\n&quot;</span>, num_tracks);\n    fflush(stdout);\n    try_jukebox_start();\n}\n\n<span class=\"keyword\">static</span> <span class=\"keywordtype\">void</span> tracks_moved(<a class=\"code\" href=\"group__types.html#ga1bcf54cbc117a20ab2c15e59eb3a8174\" title=\"A playlist handle.\">sp_playlist</a> *pl, <span class=\"keyword\">const</span> <span class=\"keywordtype\">int</span> *tracks,\n                         <span class=\"keywordtype\">int</span> num_tracks, <span class=\"keywordtype\">int</span> new_position, <span class=\"keywordtype\">void</span> *userdata)\n{\n    <span class=\"keywordflow\">if</span> (pl != g_jukeboxlist)\n        <span class=\"keywordflow\">return</span>;\n\n    printf(<span class=\"stringliteral\">&quot;jukebox: %d tracks were moved around\\n&quot;</span>, num_tracks);\n    fflush(stdout);\n    try_jukebox_start();\n}\n\n<span class=\"keyword\">static</span> <span class=\"keywordtype\">void</span> playlist_renamed(<a class=\"code\" href=\"group__types.html#ga1bcf54cbc117a20ab2c15e59eb3a8174\" title=\"A playlist handle.\">sp_playlist</a> *pl, <span class=\"keywordtype\">void</span> *userdata)\n{\n    <span class=\"keyword\">const</span> <span class=\"keywordtype\">char</span> *name = <a name=\"a8\"></a><a class=\"code\" href=\"group__playlist.html#ga61b7e33cc1aedb4e31a2af75ae0ac8cc\">sp_playlist_name</a>(pl);\n\n    <span class=\"keywordflow\">if</span> (!strcasecmp(name, g_listname)) {\n        g_jukeboxlist = pl;\n        g_track_index = 0;\n        try_jukebox_start();\n    } <span class=\"keywordflow\">else</span> <span class=\"keywordflow\">if</span> (g_jukeboxlist == pl) {\n        printf(<span class=\"stringliteral\">&quot;jukebox: current playlist renamed to \\&quot;%s\\&quot;.\\n&quot;</span>, name);\n        g_jukeboxlist = NULL;\n        g_currenttrack = NULL;\n        <a class=\"code\" href=\"group__session.html#gafa7ee2803f119451bb8be3bf28746975\">sp_session_player_unload</a>(g_sess);\n    }\n}\n\n<span class=\"keyword\">static</span> <a name=\"_a9\"></a><a class=\"code\" href=\"structsp__playlist__callbacks.html\">sp_playlist_callbacks</a> pl_callbacks = {\n    .tracks_added = &amp;tracks_added,\n    .tracks_removed = &amp;tracks_removed,\n    .tracks_moved = &amp;tracks_moved,\n    .playlist_renamed = &amp;playlist_renamed,\n};\n\n\n<span class=\"comment\">/* --------------------  PLAYLIST CONTAINER CALLBACKS  --------------------- */</span>\n<span class=\"keyword\">static</span> <span class=\"keywordtype\">void</span> playlist_added(<a class=\"code\" href=\"group__types.html#ga45a2febbe167483e48dab8d606d462d7\" title=\"A playlist container (playlist containing other playlists) handle.\">sp_playlistcontainer</a> *pc, <a class=\"code\" href=\"group__types.html#ga1bcf54cbc117a20ab2c15e59eb3a8174\" title=\"A playlist handle.\">sp_playlist</a> *pl,\n                           <span class=\"keywordtype\">int</span> position, <span class=\"keywordtype\">void</span> *userdata)\n{\n    <a name=\"a10\"></a><a class=\"code\" href=\"group__playlist.html#gab15fca12d387c69b4998a4d2b48e5b32\">sp_playlist_add_callbacks</a>(pl, &amp;pl_callbacks, NULL);\n\n    <span class=\"keywordflow\">if</span> (!strcasecmp(<a class=\"code\" href=\"group__playlist.html#ga61b7e33cc1aedb4e31a2af75ae0ac8cc\">sp_playlist_name</a>(pl), g_listname)) {\n        g_jukeboxlist = pl;\n        try_jukebox_start();\n    }\n}\n\n<span class=\"keyword\">static</span> <span class=\"keywordtype\">void</span> playlist_removed(<a class=\"code\" href=\"group__types.html#ga45a2febbe167483e48dab8d606d462d7\" title=\"A playlist container (playlist containing other playlists) handle.\">sp_playlistcontainer</a> *pc, <a class=\"code\" href=\"group__types.html#ga1bcf54cbc117a20ab2c15e59eb3a8174\" title=\"A playlist handle.\">sp_playlist</a> *pl,\n                             <span class=\"keywordtype\">int</span> position, <span class=\"keywordtype\">void</span> *userdata)\n{\n    <a name=\"a11\"></a><a class=\"code\" href=\"group__playlist.html#ga7fcbf909a0fa8bf25f0b1d1e7dd0e160\">sp_playlist_remove_callbacks</a>(pl, &amp;pl_callbacks, NULL);\n}\n\n\n<span class=\"keyword\">static</span> <span class=\"keywordtype\">void</span> container_loaded(<a class=\"code\" href=\"group__types.html#ga45a2febbe167483e48dab8d606d462d7\" title=\"A playlist container (playlist containing other playlists) handle.\">sp_playlistcontainer</a> *pc, <span class=\"keywordtype\">void</span> *userdata)\n{\n    fprintf(stderr, <span class=\"stringliteral\">&quot;jukebox: Rootlist synchronized (%d playlists)\\n&quot;</span>,\n        <a name=\"a12\"></a><a class=\"code\" href=\"group__playlist.html#ga7a1cbf558b2b364b8249d4ce432df700\">sp_playlistcontainer_num_playlists</a>(pc));\n}\n\n\n<span class=\"keyword\">static</span> <a name=\"_a13\"></a><a class=\"code\" href=\"structsp__playlistcontainer__callbacks.html\">sp_playlistcontainer_callbacks</a> pc_callbacks = {\n    .playlist_added = &amp;playlist_added,\n    .playlist_removed = &amp;playlist_removed,\n    .container_loaded = &amp;container_loaded,\n};\n\n\n<span class=\"comment\">/* ---------------------------  SESSION CALLBACKS  ------------------------- */</span>\n<span class=\"keyword\">static</span> <span class=\"keywordtype\">void</span> logged_in(<a class=\"code\" href=\"group__types.html#ga70dd19c6f824cf6a159575aa4c128b53\" title=\"Representation of a session.\">sp_session</a> *sess, <a class=\"code\" href=\"group__error.html#gafd27986ce4cd9eeaeca8adda83c9eb6b\">sp_error</a> error)\n{\n    <a class=\"code\" href=\"group__types.html#ga45a2febbe167483e48dab8d606d462d7\" title=\"A playlist container (playlist containing other playlists) handle.\">sp_playlistcontainer</a> *pc = <a name=\"a14\"></a><a class=\"code\" href=\"group__session.html#ga319767f0b795f1c46a08390b587c5671\">sp_session_playlistcontainer</a>(sess);\n    <span class=\"keywordtype\">int</span> i;\n\n    <span class=\"keywordflow\">if</span> (<a class=\"code\" href=\"group__error.html#ggafd27986ce4cd9eeaeca8adda83c9eb6ba16cb277dc84328e4b2c0cf6d5a0c0b8d\" title=\"No errors encountered.\">SP_ERROR_OK</a> != error) {\n        fprintf(stderr, <span class=\"stringliteral\">&quot;jukebox: Login failed: %s\\n&quot;</span>,\n            <a name=\"a15\"></a><a class=\"code\" href=\"group__error.html#ga983dee341d3c2008830513b7cffe7bf3\">sp_error_message</a>(error));\n        exit(2);\n    }\n\n    <a name=\"a16\"></a><a class=\"code\" href=\"group__playlist.html#ga1976cb49c391cdd2dbe7c40d1bc71570\">sp_playlistcontainer_add_callbacks</a>(\n        pc,\n        &amp;pc_callbacks,\n        NULL);\n\n    printf(<span class=\"stringliteral\">&quot;jukebox: Looking at %d playlists\\n&quot;</span>, <a class=\"code\" href=\"group__playlist.html#ga7a1cbf558b2b364b8249d4ce432df700\">sp_playlistcontainer_num_playlists</a>(pc));\n\n    <span class=\"keywordflow\">for</span> (i = 0; i &lt; <a class=\"code\" href=\"group__playlist.html#ga7a1cbf558b2b364b8249d4ce432df700\">sp_playlistcontainer_num_playlists</a>(pc); ++i) {\n        <a class=\"code\" href=\"group__types.html#ga1bcf54cbc117a20ab2c15e59eb3a8174\" title=\"A playlist handle.\">sp_playlist</a> *pl = <a name=\"a17\"></a><a class=\"code\" href=\"group__playlist.html#ga5ddd8c8064c281a14c6fd7877f522dc6\">sp_playlistcontainer_playlist</a>(pc, i);\n\n        <a class=\"code\" href=\"group__playlist.html#gab15fca12d387c69b4998a4d2b48e5b32\">sp_playlist_add_callbacks</a>(pl, &amp;pl_callbacks, NULL);\n\n        <span class=\"keywordflow\">if</span> (!strcasecmp(<a class=\"code\" href=\"group__playlist.html#ga61b7e33cc1aedb4e31a2af75ae0ac8cc\">sp_playlist_name</a>(pl), g_listname)) {\n            g_jukeboxlist = pl;\n            try_jukebox_start();\n        }\n    }\n\n    <span class=\"keywordflow\">if</span> (!g_jukeboxlist) {\n        printf(<span class=\"stringliteral\">&quot;jukebox: No such playlist. Waiting for one to pop up...\\n&quot;</span>);\n        fflush(stdout);\n    }\n}\n\n<span class=\"keyword\">static</span> <span class=\"keywordtype\">void</span> notify_main_thread(<a class=\"code\" href=\"group__types.html#ga70dd19c6f824cf6a159575aa4c128b53\" title=\"Representation of a session.\">sp_session</a> *sess)\n{\n    pthread_mutex_lock(&amp;g_notify_mutex);\n    g_notify_do = 1;\n    pthread_cond_signal(&amp;g_notify_cond);\n    pthread_mutex_unlock(&amp;g_notify_mutex);\n}\n\n<span class=\"keyword\">static</span> <span class=\"keywordtype\">int</span> music_delivery(<a class=\"code\" href=\"group__types.html#ga70dd19c6f824cf6a159575aa4c128b53\" title=\"Representation of a session.\">sp_session</a> *sess, <span class=\"keyword\">const</span> <a name=\"_a18\"></a><a class=\"code\" href=\"structsp__audioformat.html\">sp_audioformat</a> *format,\n                          <span class=\"keyword\">const</span> <span class=\"keywordtype\">void</span> *frames, <span class=\"keywordtype\">int</span> num_frames)\n{\n    audio_fifo_t *af = &amp;g_audiofifo;\n    audio_fifo_data_t *afd;\n    <span class=\"keywordtype\">size_t</span> s;\n\n    <span class=\"keywordflow\">if</span> (num_frames == 0)\n        <span class=\"keywordflow\">return</span> 0; <span class=\"comment\">// Audio discontinuity, do nothing</span>\n\n    pthread_mutex_lock(&amp;af-&gt;mutex);\n\n    <span class=\"comment\">/* Buffer one second of audio */</span>\n    <span class=\"keywordflow\">if</span> (af-&gt;qlen &gt; format-&gt;<a name=\"a19\"></a><a class=\"code\" href=\"structsp__audioformat.html#a2eb66d38a418d5c0afe284d4d45a619d\" title=\"Audio sample rate, in samples per second.\">sample_rate</a>) {\n        pthread_mutex_unlock(&amp;af-&gt;mutex);\n\n        <span class=\"keywordflow\">return</span> 0;\n    }\n\n    s = num_frames * <span class=\"keyword\">sizeof</span>(int16_t) * format-&gt;<a name=\"a20\"></a><a class=\"code\" href=\"structsp__audioformat.html#ab6b47d8d0ebfaab73229d707dc8bf0b8\" title=\"Number of channels. Currently 1 or 2.\">channels</a>;\n\n    afd = malloc(<span class=\"keyword\">sizeof</span>(*afd) + s);\n    memcpy(afd-&gt;samples, frames, s);\n\n    afd-&gt;nsamples = num_frames;\n\n    afd-&gt;rate = format-&gt;<a class=\"code\" href=\"structsp__audioformat.html#a2eb66d38a418d5c0afe284d4d45a619d\" title=\"Audio sample rate, in samples per second.\">sample_rate</a>;\n    afd-&gt;channels = format-&gt;<a class=\"code\" href=\"structsp__audioformat.html#ab6b47d8d0ebfaab73229d707dc8bf0b8\" title=\"Number of channels. Currently 1 or 2.\">channels</a>;\n\n    TAILQ_INSERT_TAIL(&amp;af-&gt;q, afd, link);\n    af-&gt;qlen += num_frames;\n\n    pthread_cond_signal(&amp;af-&gt;cond);\n    pthread_mutex_unlock(&amp;af-&gt;mutex);\n\n    <span class=\"keywordflow\">return</span> num_frames;\n}\n\n\n<span class=\"keyword\">static</span> <span class=\"keywordtype\">void</span> end_of_track(<a class=\"code\" href=\"group__types.html#ga70dd19c6f824cf6a159575aa4c128b53\" title=\"Representation of a session.\">sp_session</a> *sess)\n{\n    pthread_mutex_lock(&amp;g_notify_mutex);\n    g_playback_done = 1;\n    g_notify_do = 1;\n    pthread_cond_signal(&amp;g_notify_cond);\n    pthread_mutex_unlock(&amp;g_notify_mutex);\n}\n\n\n<span class=\"keyword\">static</span> <span class=\"keywordtype\">void</span> metadata_updated(<a class=\"code\" href=\"group__types.html#ga70dd19c6f824cf6a159575aa4c128b53\" title=\"Representation of a session.\">sp_session</a> *sess)\n{\n    try_jukebox_start();\n}\n\n<span class=\"keyword\">static</span> <span class=\"keywordtype\">void</span> play_token_lost(<a class=\"code\" href=\"group__types.html#ga70dd19c6f824cf6a159575aa4c128b53\" title=\"Representation of a session.\">sp_session</a> *sess)\n{\n    audio_fifo_flush(&amp;g_audiofifo);\n\n    <span class=\"keywordflow\">if</span> (g_currenttrack != NULL) {\n        <a class=\"code\" href=\"group__session.html#gafa7ee2803f119451bb8be3bf28746975\">sp_session_player_unload</a>(g_sess);\n        g_currenttrack = NULL;\n    }\n}\n\n<span class=\"keyword\">static</span> <a name=\"_a21\"></a><a class=\"code\" href=\"structsp__session__callbacks.html\">sp_session_callbacks</a> session_callbacks = {\n    .logged_in = &amp;logged_in,\n    .notify_main_thread = &amp;notify_main_thread,\n    .music_delivery = &amp;music_delivery,\n    .metadata_updated = &amp;metadata_updated,\n    .play_token_lost = &amp;play_token_lost,\n    .log_message = NULL,\n    .end_of_track = &amp;end_of_track,\n};\n\n<span class=\"keyword\">static</span> <a name=\"_a22\"></a><a class=\"code\" href=\"structsp__session__config.html\">sp_session_config</a> spconfig = {\n    .api_version = SPOTIFY_API_VERSION,\n    .cache_location = <span class=\"stringliteral\">&quot;tmp&quot;</span>,\n    .settings_location = <span class=\"stringliteral\">&quot;tmp&quot;</span>,\n    .application_key = g_appkey,\n    .application_key_size = 0, <span class=\"comment\">// Set in main()</span>\n    .user_agent = <span class=\"stringliteral\">&quot;spotify-jukebox-example&quot;</span>,\n    .callbacks = &amp;session_callbacks,\n    NULL,\n};\n<span class=\"comment\">/* -------------------------  END SESSION CALLBACKS  ----------------------- */</span>\n\n\n<span class=\"keyword\">static</span> <span class=\"keywordtype\">void</span> track_ended(<span class=\"keywordtype\">void</span>)\n{\n    <span class=\"keywordtype\">int</span> tracks = 0;\n\n    <span class=\"keywordflow\">if</span> (g_currenttrack) {\n        g_currenttrack = NULL;\n        <a class=\"code\" href=\"group__session.html#gafa7ee2803f119451bb8be3bf28746975\">sp_session_player_unload</a>(g_sess);\n        <span class=\"keywordflow\">if</span> (g_remove_tracks) {\n            <a name=\"a23\"></a><a class=\"code\" href=\"group__playlist.html#gabd62cd7ff9484b4c31ff7f159ec41b6a\">sp_playlist_remove_tracks</a>(g_jukeboxlist, &amp;tracks, 1);\n        } <span class=\"keywordflow\">else</span> {\n            ++g_track_index;\n            try_jukebox_start();\n        }\n    }\n}\n\n<span class=\"keyword\">static</span> <span class=\"keywordtype\">void</span> usage(<span class=\"keyword\">const</span> <span class=\"keywordtype\">char</span> *progname)\n{\n    fprintf(stderr, <span class=\"stringliteral\">&quot;usage: %s -u &lt;username&gt; -p &lt;password&gt; -l &lt;listname&gt; [-d]\\n&quot;</span>, progname);\n    fprintf(stderr, <span class=\"stringliteral\">&quot;warning: -d will delete the tracks played from the list!\\n&quot;</span>);\n}\n\n<span class=\"keywordtype\">int</span> main(<span class=\"keywordtype\">int</span> argc, <span class=\"keywordtype\">char</span> **argv)\n{\n    <a class=\"code\" href=\"group__types.html#ga70dd19c6f824cf6a159575aa4c128b53\" title=\"Representation of a session.\">sp_session</a> *sp;\n    <a class=\"code\" href=\"group__error.html#gafd27986ce4cd9eeaeca8adda83c9eb6b\">sp_error</a> err;\n    <span class=\"keywordtype\">int</span> next_timeout = 0;\n    <span class=\"keyword\">const</span> <span class=\"keywordtype\">char</span> *username = NULL;\n    <span class=\"keyword\">const</span> <span class=\"keywordtype\">char</span> *password = NULL;\n    <span class=\"keywordtype\">int</span> opt;\n\n    <span class=\"keywordflow\">while</span> ((opt = getopt(argc, argv, <span class=\"stringliteral\">&quot;u:p:l:d&quot;</span>)) != EOF) {\n        <span class=\"keywordflow\">switch</span> (opt) {\n        <span class=\"keywordflow\">case</span> <span class=\"charliteral\">&#39;u&#39;</span>:\n            username = optarg;\n            <span class=\"keywordflow\">break</span>;\n\n        <span class=\"keywordflow\">case</span> <span class=\"charliteral\">&#39;p&#39;</span>:\n            password = optarg;\n            <span class=\"keywordflow\">break</span>;\n\n        <span class=\"keywordflow\">case</span> <span class=\"charliteral\">&#39;l&#39;</span>:\n            g_listname = optarg;\n            <span class=\"keywordflow\">break</span>;\n\n        <span class=\"keywordflow\">case</span> <span class=\"charliteral\">&#39;d&#39;</span>:\n            g_remove_tracks = 1;\n            <span class=\"keywordflow\">break</span>;\n\n        <span class=\"keywordflow\">default</span>:\n            exit(1);\n        }\n    }\n\n    <span class=\"keywordflow\">if</span> (!username || !password || !g_listname) {\n        usage(basename(argv[0]));\n        exit(1);\n    }\n\n    audio_init(&amp;g_audiofifo);\n\n    <span class=\"comment\">/* Create session */</span>\n    spconfig.<a name=\"a24\"></a><a class=\"code\" href=\"structsp__session__config.html#ab10b332fe29b941162fd1d9ea1003b82\" title=\"The size of the application key in bytes.\">application_key_size</a> = g_appkey_size;\n\n    err = <a name=\"a25\"></a><a class=\"code\" href=\"group__session.html#gaf2891f2daced4ff6da84219d6376b3aa\">sp_session_create</a>(&amp;spconfig, &amp;sp);\n\n    <span class=\"keywordflow\">if</span> (<a class=\"code\" href=\"group__error.html#ggafd27986ce4cd9eeaeca8adda83c9eb6ba16cb277dc84328e4b2c0cf6d5a0c0b8d\" title=\"No errors encountered.\">SP_ERROR_OK</a> != err) {\n        fprintf(stderr, <span class=\"stringliteral\">&quot;Unable to create session: %s\\n&quot;</span>,\n            <a class=\"code\" href=\"group__error.html#ga983dee341d3c2008830513b7cffe7bf3\">sp_error_message</a>(err));\n        exit(1);\n    }\n\n    g_sess = sp;\n\n    pthread_mutex_init(&amp;g_notify_mutex, NULL);\n    pthread_cond_init(&amp;g_notify_cond, NULL);\n\n    <a name=\"a26\"></a><a class=\"code\" href=\"group__session.html#ga4533a992a120cacb109c892a852afe2a\">sp_session_login</a>(sp, username, password, 0, NULL);\n    pthread_mutex_lock(&amp;g_notify_mutex);\n\n    <span class=\"keywordflow\">for</span> (;;) {\n        <span class=\"keywordflow\">if</span> (next_timeout == 0) {\n            <span class=\"keywordflow\">while</span>(!g_notify_do)\n                pthread_cond_wait(&amp;g_notify_cond, &amp;g_notify_mutex);\n        } <span class=\"keywordflow\">else</span> {\n            <span class=\"keyword\">struct </span>timespec ts;\n\n<span class=\"preprocessor\">#if _POSIX_TIMERS &gt; 0</span>\n<span class=\"preprocessor\"></span>            clock_gettime(CLOCK_REALTIME, &amp;ts);\n<span class=\"preprocessor\">#else</span>\n<span class=\"preprocessor\"></span>            <span class=\"keyword\">struct </span>timeval tv;\n            gettimeofday(&amp;tv, NULL);\n            TIMEVAL_TO_TIMESPEC(&amp;tv, &amp;ts);\n<span class=\"preprocessor\">#endif</span>\n<span class=\"preprocessor\"></span>            ts.tv_sec += next_timeout / 1000;\n            ts.tv_nsec += (next_timeout % 1000) * 1000000;\n\n            pthread_cond_timedwait(&amp;g_notify_cond, &amp;g_notify_mutex, &amp;ts);\n        }\n\n        g_notify_do = 0;\n        pthread_mutex_unlock(&amp;g_notify_mutex);\n\n        <span class=\"keywordflow\">if</span> (g_playback_done) {\n            track_ended();\n            g_playback_done = 0;\n        }\n\n        <span class=\"keywordflow\">do</span> {\n            <a name=\"a27\"></a><a class=\"code\" href=\"group__session.html#gaff27cb730db6debf55e750e39e7fadd7\">sp_session_process_events</a>(sp, &amp;next_timeout);\n        } <span class=\"keywordflow\">while</span> (next_timeout == 0);\n\n        pthread_mutex_lock(&amp;g_notify_mutex);\n    }\n\n    <span class=\"keywordflow\">return</span> 0;\n}\n</pre></div> </div>\n</div>\n<hr size=\"1\"><address style=\"text-align: right;\"><small>\nGenerated on Wed Jun 13 2012 14:22:40.<br>\nCopyright &copy; 2006&ndash;2012 Spotify Ltd</small></address>\n</body>\n</html>\n"
  },
  {
    "path": "libspotify/docs/html/modules.html",
    "content": "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\n<html xmlns=\"http://www.w3.org/1999/xhtml\">\n<head>\n<meta http-equiv=\"Content-Type\" content=\"text/xhtml;charset=UTF-8\"/>\n<title>libspotify: Module Index</title>\n<link href=\"tabs.css\" rel=\"stylesheet\" type=\"text/css\"/>\n<link href=\"doxygen.css\" rel=\"stylesheet\" type=\"text/css\"/>\n</head>\n<body>\n<!-- Generated by Doxygen 1.7.1 -->\n<div class=\"navigation\" id=\"top\">\n  <div class=\"tabs\">\n    <ul class=\"tablist\">\n      <li><a href=\"index.html\"><span>Main&nbsp;Page</span></a></li>\n      <li class=\"current\"><a href=\"modules.html\"><span>Modules</span></a></li>\n      <li><a href=\"annotated.html\"><span>Data&nbsp;Structures</span></a></li>\n      <li><a href=\"files.html\"><span>Files</span></a></li>\n      <li><a href=\"examples.html\"><span>Examples</span></a></li>\n    </ul>\n  </div>\n</div>\n<div class=\"header\">\n  <div class=\"headertitle\">\n<h1>Modules</h1>  </div>\n</div>\n<div class=\"contents\">\nHere is a list of all modules:<ul>\n<li><a class=\"el\" href=\"group__types.html\">Spotify types &amp; structs</a></li>\n<li><a class=\"el\" href=\"group__error.html\">Error Handling</a></li>\n<li><a class=\"el\" href=\"group__session.html\">Session handling</a></li>\n<li><a class=\"el\" href=\"group__link.html\">Links (Spotify URIs)</a></li>\n<li><a class=\"el\" href=\"group__track.html\">Track subsystem</a></li>\n<li><a class=\"el\" href=\"group__album.html\">Album subsystem</a></li>\n<li><a class=\"el\" href=\"group__artist.html\">Artist subsystem</a></li>\n<li><a class=\"el\" href=\"group__albumbrowse.html\">Album browsing</a></li>\n<li><a class=\"el\" href=\"group__artistbrowse.html\">Artist browsing</a></li>\n<li><a class=\"el\" href=\"group__image.html\">Image handling</a></li>\n<li><a class=\"el\" href=\"group__search.html\">Search subsystem</a></li>\n<li><a class=\"el\" href=\"group__playlist.html\">Playlist subsystem</a></li>\n<li><a class=\"el\" href=\"group__user.html\">User handling</a></li>\n<li><a class=\"el\" href=\"group__toplist.html\">Toplist handling</a></li>\n<li><a class=\"el\" href=\"group__inbox.html\">Inbox subsystem</a></li>\n</ul>\n</div>\n<hr size=\"1\"><address style=\"text-align: right;\"><small>\nGenerated on Wed Jun 13 2012 14:22:40.<br>\nCopyright &copy; 2006&ndash;2012 Spotify Ltd</small></address>\n</body>\n</html>\n"
  },
  {
    "path": "libspotify/docs/html/search_8c-example.html",
    "content": "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\n<html xmlns=\"http://www.w3.org/1999/xhtml\">\n<head>\n<meta http-equiv=\"Content-Type\" content=\"text/xhtml;charset=UTF-8\"/>\n<title>libspotify: search.c</title>\n<link href=\"tabs.css\" rel=\"stylesheet\" type=\"text/css\"/>\n<link href=\"doxygen.css\" rel=\"stylesheet\" type=\"text/css\"/>\n</head>\n<body>\n<!-- Generated by Doxygen 1.7.1 -->\n<div class=\"navigation\" id=\"top\">\n  <div class=\"tabs\">\n    <ul class=\"tablist\">\n      <li><a href=\"index.html\"><span>Main&nbsp;Page</span></a></li>\n      <li><a href=\"modules.html\"><span>Modules</span></a></li>\n      <li><a href=\"annotated.html\"><span>Data&nbsp;Structures</span></a></li>\n      <li><a href=\"files.html\"><span>Files</span></a></li>\n      <li><a href=\"examples.html\"><span>Examples</span></a></li>\n    </ul>\n  </div>\n</div>\n<div class=\"header\">\n  <div class=\"headertitle\">\n<h1>search.c</h1>  </div>\n</div>\n<div class=\"contents\">\n<p>The search.c example shows how you can use search functions. It is part of the spshell program</p>\n<div class=\"fragment\"><pre class=\"fragment\">\n<span class=\"preprocessor\">#include &lt;string.h&gt;</span>\n\n<span class=\"preprocessor\">#include &quot;spshell.h&quot;</span>\n<span class=\"preprocessor\">#include &quot;cmd.h&quot;</span>\n\n\n<span class=\"keyword\">static</span> <span class=\"keywordtype\">void</span> print_album(<a class=\"code\" href=\"group__types.html#ga6fd3e5de729c429fef3ff18ece6dcfad\" title=\"An album handle.\">sp_album</a> *album)\n{\n    printf(<span class=\"stringliteral\">&quot;  Album \\&quot;%s\\&quot; (%d)\\n&quot;</span>,\n           <a name=\"a0\"></a><a class=\"code\" href=\"group__album.html#ga0e828c991a8184d60026513f944e19ad\">sp_album_name</a>(album),\n           <a name=\"a1\"></a><a class=\"code\" href=\"group__album.html#ga2aadf934b0af43c3ef6ee98b6a8065fd\">sp_album_year</a>(album));\n}\n\n<span class=\"keyword\">static</span> <span class=\"keywordtype\">void</span> print_artist(<a class=\"code\" href=\"group__types.html#ga31764fbd69618c10be173c6c03d4c1bc\" title=\"An artist handle.\">sp_artist</a> *artist)\n{\n    printf(<span class=\"stringliteral\">&quot;  Artist \\&quot;%s\\&quot;\\n&quot;</span>, <a name=\"a2\"></a><a class=\"code\" href=\"group__artist.html#gad2895555bb48514986823733a7afe5e2\">sp_artist_name</a>(artist));\n}\n\n<span class=\"keyword\">static</span> <span class=\"keywordtype\">void</span> print_search(<a class=\"code\" href=\"group__types.html#gac95893a6b23d4b19f6f149eed6ead1fd\" title=\"A handle to a search result.\">sp_search</a> *search)\n{\n    <span class=\"keywordtype\">int</span> i;\n\n    printf(<span class=\"stringliteral\">&quot;Query          : %s\\n&quot;</span>, <a name=\"a3\"></a><a class=\"code\" href=\"group__search.html#ga127e9c2bf98e3602ecfc2926b9d242bf\">sp_search_query</a>(search));\n    printf(<span class=\"stringliteral\">&quot;Did you mean   : %s\\n&quot;</span>, <a name=\"a4\"></a><a class=\"code\" href=\"group__search.html#ga8561c1da8b93ecdc8f2d325a9d19199b\">sp_search_did_you_mean</a>(search));\n    printf(<span class=\"stringliteral\">&quot;Tracks in total: %d\\n&quot;</span>, <a name=\"a5\"></a><a class=\"code\" href=\"group__search.html#gab4e50582c517b4639fd1afd6fb011587\">sp_search_total_tracks</a>(search));\n    puts(<span class=\"stringliteral\">&quot;&quot;</span>);\n\n    <span class=\"keywordflow\">for</span> (i = 0; i &lt; <a name=\"a6\"></a><a class=\"code\" href=\"group__search.html#ga1dd18cf7b3b3b7f4bf6e92a2140378d0\">sp_search_num_tracks</a>(search); ++i)\n        print_track(<a name=\"a7\"></a><a class=\"code\" href=\"group__search.html#gae9da7ca59ce0bbd73f7bcef4e15c4da8\">sp_search_track</a>(search, i));\n\n    puts(<span class=\"stringliteral\">&quot;&quot;</span>);\n\n    <span class=\"keywordflow\">for</span> (i = 0; i &lt; <a name=\"a8\"></a><a class=\"code\" href=\"group__search.html#ga0c456a6396c4c05fbc8677ea641ef1f7\">sp_search_num_albums</a>(search); ++i)\n        print_album(<a name=\"a9\"></a><a class=\"code\" href=\"group__search.html#ga4ba7723e70db0c6a4569c4bcd44f0e98\">sp_search_album</a>(search, i));\n\n    puts(<span class=\"stringliteral\">&quot;&quot;</span>);\n\n    <span class=\"keywordflow\">for</span> (i = 0; i &lt; <a name=\"a10\"></a><a class=\"code\" href=\"group__search.html#gabd375a613c2dadecad8c13f8aca6f2d3\">sp_search_num_artists</a>(search); ++i)\n        print_artist(<a name=\"a11\"></a><a class=\"code\" href=\"group__search.html#ga79b3d532d5a20a3b2bf2a087eead7888\">sp_search_artist</a>(search, i));\n\n    puts(<span class=\"stringliteral\">&quot;&quot;</span>);\n\n    <span class=\"keywordflow\">for</span> (i = 0; i &lt; <a name=\"a12\"></a><a class=\"code\" href=\"group__search.html#gaa9f007f439d8241bf632f9abb8d926c9\">sp_search_num_playlists</a>(search); ++i) {\n        <span class=\"comment\">// print some readily available metadata, the rest will</span>\n        <span class=\"comment\">// be available from the sp_playlist object loaded through</span>\n        <span class=\"comment\">// sp_search_playlist().</span>\n        printf(<span class=\"stringliteral\">&quot;  Playlist \\&quot;%s\\&quot;\\n&quot;</span>, <a name=\"a13\"></a><a class=\"code\" href=\"group__search.html#ga933cd5d5a0ccca9906082ca4549a4ed7\">sp_search_playlist_name</a>(search, i));\n    }\n}\n\n<span class=\"keyword\">static</span> <span class=\"keywordtype\">void</span> SP_CALLCONV search_complete(<a class=\"code\" href=\"group__types.html#gac95893a6b23d4b19f6f149eed6ead1fd\" title=\"A handle to a search result.\">sp_search</a> *search, <span class=\"keywordtype\">void</span> *userdata)\n{\n    <span class=\"keywordflow\">if</span> (<a name=\"a14\"></a><a class=\"code\" href=\"group__search.html#ga7cf655e37a823f952d30270d4fb60f10\">sp_search_error</a>(search) == <a name=\"a15\"></a><a class=\"code\" href=\"group__error.html#ggafd27986ce4cd9eeaeca8adda83c9eb6ba16cb277dc84328e4b2c0cf6d5a0c0b8d\" title=\"No errors encountered.\">SP_ERROR_OK</a>)\n        print_search(search);\n    <span class=\"keywordflow\">else</span>\n        fprintf(stderr, <span class=\"stringliteral\">&quot;Failed to search: %s\\n&quot;</span>,\n                <a name=\"a16\"></a><a class=\"code\" href=\"group__error.html#ga983dee341d3c2008830513b7cffe7bf3\">sp_error_message</a>(<a class=\"code\" href=\"group__search.html#ga7cf655e37a823f952d30270d4fb60f10\">sp_search_error</a>(search)));\n\n    <a name=\"a17\"></a><a class=\"code\" href=\"group__search.html#ga4e01d43067d9f8c533c985f90143821b\">sp_search_release</a>(search);\n    cmd_done();\n}\n\n\n\n<span class=\"keyword\">static</span> <span class=\"keywordtype\">void</span> search_usage(<span class=\"keywordtype\">void</span>)\n{\n    fprintf(stderr, <span class=\"stringliteral\">&quot;Usage: search &lt;query&gt;\\n&quot;</span>);\n}\n\n\n<span class=\"keywordtype\">int</span> cmd_search(<span class=\"keywordtype\">int</span> argc, <span class=\"keywordtype\">char</span> **argv)\n{\n    <span class=\"keywordtype\">char</span> query[1024];\n    <span class=\"keywordtype\">int</span> i;\n\n    <span class=\"keywordflow\">if</span> (argc &lt; 2) {\n        search_usage();\n        <span class=\"keywordflow\">return</span> -1;\n    }\n\n    query[0] = 0;\n    <span class=\"keywordflow\">for</span>(i = 1; i &lt; argc; i++)\n        snprintf(query + strlen(query), <span class=\"keyword\">sizeof</span>(query) - strlen(query), <span class=\"stringliteral\">&quot;%s%s&quot;</span>,\n             i == 1 ? <span class=\"stringliteral\">&quot;&quot;</span> : <span class=\"stringliteral\">&quot; &quot;</span>, argv[i]);\n\n    <a name=\"a18\"></a><a class=\"code\" href=\"group__search.html#ga2f64dfbcc1313e7d5179998cb28208d4\">sp_search_create</a>(g_session, query, 0, 100, 0, 100, 0, 100, 0, 100, SP_SEARCH_STANDARD, &amp;search_complete, NULL);\n    <span class=\"keywordflow\">return</span> 0;\n}\n\n\n<span class=\"keywordtype\">int</span> cmd_whatsnew(<span class=\"keywordtype\">int</span> argc, <span class=\"keywordtype\">char</span> **argv)\n{\n    <a class=\"code\" href=\"group__search.html#ga2f64dfbcc1313e7d5179998cb28208d4\">sp_search_create</a>(g_session, <span class=\"stringliteral\">&quot;tag:new&quot;</span>, 0, 0, 0, 250, 0, 0, 0, 0, SP_SEARCH_STANDARD, &amp;search_complete, NULL);\n    <span class=\"keywordflow\">return</span> 0;\n}\n</pre></div> </div>\n</div>\n<hr size=\"1\"><address style=\"text-align: right;\"><small>\nGenerated on Wed Jun 13 2012 14:22:40.<br>\nCopyright &copy; 2006&ndash;2012 Spotify Ltd</small></address>\n</body>\n</html>\n"
  },
  {
    "path": "libspotify/docs/html/structsp__audio__buffer__stats.html",
    "content": "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\n<html xmlns=\"http://www.w3.org/1999/xhtml\">\n<head>\n<meta http-equiv=\"Content-Type\" content=\"text/xhtml;charset=UTF-8\"/>\n<title>libspotify: sp_audio_buffer_stats Struct Reference</title>\n<link href=\"tabs.css\" rel=\"stylesheet\" type=\"text/css\"/>\n<link href=\"doxygen.css\" rel=\"stylesheet\" type=\"text/css\"/>\n</head>\n<body>\n<!-- Generated by Doxygen 1.7.1 -->\n<div class=\"navigation\" id=\"top\">\n  <div class=\"tabs\">\n    <ul class=\"tablist\">\n      <li><a href=\"index.html\"><span>Main&nbsp;Page</span></a></li>\n      <li><a href=\"modules.html\"><span>Modules</span></a></li>\n      <li class=\"current\"><a href=\"annotated.html\"><span>Data&nbsp;Structures</span></a></li>\n      <li><a href=\"files.html\"><span>Files</span></a></li>\n      <li><a href=\"examples.html\"><span>Examples</span></a></li>\n    </ul>\n  </div>\n  <div class=\"tabs2\">\n    <ul class=\"tablist\">\n      <li><a href=\"annotated.html\"><span>Data&nbsp;Structures</span></a></li>\n      <li><a href=\"functions.html\"><span>Data&nbsp;Fields</span></a></li>\n    </ul>\n  </div>\n</div>\n<div class=\"header\">\n  <div class=\"summary\">\n<a href=\"#pub-attribs\">Data Fields</a>  </div>\n  <div class=\"headertitle\">\n<h1>sp_audio_buffer_stats Struct Reference<br/>\n<small>\n[<a class=\"el\" href=\"group__session.html\">Session handling</a>]</small>\n</h1>  </div>\n</div>\n<div class=\"contents\">\n<!-- doxytag: class=\"sp_audio_buffer_stats\" -->\n<p><code>#include &lt;api.h&gt;</code></p>\n<table class=\"memberdecls\">\n<tr><td colspan=\"2\"><h2><a name=\"pub-attribs\"></a>\nData Fields</h2></td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"anchor\" id=\"a1ff9dcc75ace1cc954138fedc4c8f854\"></a><!-- doxytag: member=\"sp_audio_buffer_stats::samples\" ref=\"a1ff9dcc75ace1cc954138fedc4c8f854\" args=\"\" -->\nint&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"structsp__audio__buffer__stats.html#a1ff9dcc75ace1cc954138fedc4c8f854\">samples</a></td></tr>\n<tr><td class=\"mdescLeft\">&nbsp;</td><td class=\"mdescRight\">Samples in buffer. <br/></td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"anchor\" id=\"a85f67e5b11d5ba63b4a94f01a5009d96\"></a><!-- doxytag: member=\"sp_audio_buffer_stats::stutter\" ref=\"a85f67e5b11d5ba63b4a94f01a5009d96\" args=\"\" -->\nint&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"structsp__audio__buffer__stats.html#a85f67e5b11d5ba63b4a94f01a5009d96\">stutter</a></td></tr>\n<tr><td class=\"mdescLeft\">&nbsp;</td><td class=\"mdescRight\">Number of stutters (audio dropouts) since last query. <br/></td></tr>\n</table>\n<hr/><a name=\"_details\"></a><h2>Detailed Description</h2>\n<p>Buffer stats used by get_audio_buffer_stats callback </p>\n<hr/>The documentation for this struct was generated from the following file:<ul>\n<li><a class=\"el\" href=\"api_8h.html\">api.h</a></li>\n</ul>\n</div>\n<hr size=\"1\"><address style=\"text-align: right;\"><small>\nGenerated on Wed Jun 13 2012 14:22:40.<br>\nCopyright &copy; 2006&ndash;2012 Spotify Ltd</small></address>\n</body>\n</html>\n"
  },
  {
    "path": "libspotify/docs/html/structsp__audioformat.html",
    "content": "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\n<html xmlns=\"http://www.w3.org/1999/xhtml\">\n<head>\n<meta http-equiv=\"Content-Type\" content=\"text/xhtml;charset=UTF-8\"/>\n<title>libspotify: sp_audioformat Struct Reference</title>\n<link href=\"tabs.css\" rel=\"stylesheet\" type=\"text/css\"/>\n<link href=\"doxygen.css\" rel=\"stylesheet\" type=\"text/css\"/>\n</head>\n<body>\n<!-- Generated by Doxygen 1.7.1 -->\n<div class=\"navigation\" id=\"top\">\n  <div class=\"tabs\">\n    <ul class=\"tablist\">\n      <li><a href=\"index.html\"><span>Main&nbsp;Page</span></a></li>\n      <li><a href=\"modules.html\"><span>Modules</span></a></li>\n      <li class=\"current\"><a href=\"annotated.html\"><span>Data&nbsp;Structures</span></a></li>\n      <li><a href=\"files.html\"><span>Files</span></a></li>\n      <li><a href=\"examples.html\"><span>Examples</span></a></li>\n    </ul>\n  </div>\n  <div class=\"tabs2\">\n    <ul class=\"tablist\">\n      <li><a href=\"annotated.html\"><span>Data&nbsp;Structures</span></a></li>\n      <li><a href=\"functions.html\"><span>Data&nbsp;Fields</span></a></li>\n    </ul>\n  </div>\n</div>\n<div class=\"header\">\n  <div class=\"summary\">\n<a href=\"#pub-attribs\">Data Fields</a>  </div>\n  <div class=\"headertitle\">\n<h1>sp_audioformat Struct Reference<br/>\n<small>\n[<a class=\"el\" href=\"group__session.html\">Session handling</a>]</small>\n</h1>  </div>\n</div>\n<div class=\"contents\">\n<!-- doxytag: class=\"sp_audioformat\" -->\n<p><code>#include &lt;api.h&gt;</code></p>\n<table class=\"memberdecls\">\n<tr><td colspan=\"2\"><h2><a name=\"pub-attribs\"></a>\nData Fields</h2></td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"anchor\" id=\"af128862563608ee7e41a6d6a4e6133bc\"></a><!-- doxytag: member=\"sp_audioformat::sample_type\" ref=\"af128862563608ee7e41a6d6a4e6133bc\" args=\"\" -->\n<a class=\"el\" href=\"group__session.html#ga087d21080010768316cfb55d938eb94d\">sp_sampletype</a>&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"structsp__audioformat.html#af128862563608ee7e41a6d6a4e6133bc\">sample_type</a></td></tr>\n<tr><td class=\"mdescLeft\">&nbsp;</td><td class=\"mdescRight\">Sample type enum,. <br/></td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"anchor\" id=\"a2eb66d38a418d5c0afe284d4d45a619d\"></a><!-- doxytag: member=\"sp_audioformat::sample_rate\" ref=\"a2eb66d38a418d5c0afe284d4d45a619d\" args=\"\" -->\nint&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"structsp__audioformat.html#a2eb66d38a418d5c0afe284d4d45a619d\">sample_rate</a></td></tr>\n<tr><td class=\"mdescLeft\">&nbsp;</td><td class=\"mdescRight\">Audio sample rate, in samples per second. <br/></td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"anchor\" id=\"ab6b47d8d0ebfaab73229d707dc8bf0b8\"></a><!-- doxytag: member=\"sp_audioformat::channels\" ref=\"ab6b47d8d0ebfaab73229d707dc8bf0b8\" args=\"\" -->\nint&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"structsp__audioformat.html#ab6b47d8d0ebfaab73229d707dc8bf0b8\">channels</a></td></tr>\n<tr><td class=\"mdescLeft\">&nbsp;</td><td class=\"mdescRight\">Number of channels. Currently 1 or 2. <br/></td></tr>\n</table>\n<hr/><a name=\"_details\"></a><h2>Detailed Description</h2>\n<p>Audio format descriptor </p>\n<dl><dt><b>Examples: </b></dt><dd>\n<p><a class=\"el\" href=\"jukebox_8c-example.html#_a18\">jukebox.c</a>.</p>\n</dd>\n</dl><hr/>The documentation for this struct was generated from the following file:<ul>\n<li><a class=\"el\" href=\"api_8h.html\">api.h</a></li>\n</ul>\n</div>\n<hr size=\"1\"><address style=\"text-align: right;\"><small>\nGenerated on Wed Jun 13 2012 14:22:40.<br>\nCopyright &copy; 2006&ndash;2012 Spotify Ltd</small></address>\n</body>\n</html>\n"
  },
  {
    "path": "libspotify/docs/html/structsp__offline__sync__status.html",
    "content": "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\n<html xmlns=\"http://www.w3.org/1999/xhtml\">\n<head>\n<meta http-equiv=\"Content-Type\" content=\"text/xhtml;charset=UTF-8\"/>\n<title>libspotify: sp_offline_sync_status Struct Reference</title>\n<link href=\"tabs.css\" rel=\"stylesheet\" type=\"text/css\"/>\n<link href=\"doxygen.css\" rel=\"stylesheet\" type=\"text/css\"/>\n</head>\n<body>\n<!-- Generated by Doxygen 1.7.1 -->\n<div class=\"navigation\" id=\"top\">\n  <div class=\"tabs\">\n    <ul class=\"tablist\">\n      <li><a href=\"index.html\"><span>Main&nbsp;Page</span></a></li>\n      <li><a href=\"modules.html\"><span>Modules</span></a></li>\n      <li class=\"current\"><a href=\"annotated.html\"><span>Data&nbsp;Structures</span></a></li>\n      <li><a href=\"files.html\"><span>Files</span></a></li>\n      <li><a href=\"examples.html\"><span>Examples</span></a></li>\n    </ul>\n  </div>\n  <div class=\"tabs2\">\n    <ul class=\"tablist\">\n      <li><a href=\"annotated.html\"><span>Data&nbsp;Structures</span></a></li>\n      <li><a href=\"functions.html\"><span>Data&nbsp;Fields</span></a></li>\n    </ul>\n  </div>\n</div>\n<div class=\"header\">\n  <div class=\"summary\">\n<a href=\"#pub-attribs\">Data Fields</a>  </div>\n  <div class=\"headertitle\">\n<h1>sp_offline_sync_status Struct Reference<br/>\n<small>\n[<a class=\"el\" href=\"group__session.html\">Session handling</a>]</small>\n</h1>  </div>\n</div>\n<div class=\"contents\">\n<!-- doxytag: class=\"sp_offline_sync_status\" -->\n<p><code>#include &lt;api.h&gt;</code></p>\n<table class=\"memberdecls\">\n<tr><td colspan=\"2\"><h2><a name=\"pub-attribs\"></a>\nData Fields</h2></td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">int&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"structsp__offline__sync__status.html#a44a8a719c66266763ed184b575abce61\">queued_tracks</a></td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">int&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"structsp__offline__sync__status.html#aaeb2860d7301485d40d9f0d9bb868fbb\">done_tracks</a></td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">int&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"structsp__offline__sync__status.html#add0d4345a08fc710614be33c5a662f7c\">copied_tracks</a></td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">int&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"structsp__offline__sync__status.html#aa56788dbda2c99047cc79282caf3ffd6\">willnotcopy_tracks</a></td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">int&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"structsp__offline__sync__status.html#aa5002b69e3826edc285d19eb7ca0f582\">error_tracks</a></td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">bool&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"structsp__offline__sync__status.html#a5a2a99fdb8eeb38b3c73a44c6df68d06\">syncing</a></td></tr>\n</table>\n<hr/><a name=\"_details\"></a><h2>Detailed Description</h2>\n<p>Offline sync status </p>\n<hr/><h2>Field Documentation</h2>\n<a class=\"anchor\" id=\"add0d4345a08fc710614be33c5a662f7c\"></a><!-- doxytag: member=\"sp_offline_sync_status::copied_tracks\" ref=\"add0d4345a08fc710614be33c5a662f7c\" args=\"\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\">int <a class=\"el\" href=\"structsp__offline__sync__status.html#add0d4345a08fc710614be33c5a662f7c\">sp_offline_sync_status::copied_tracks</a></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Copied tracks/bytes is things that has been copied in current sync operation </p>\n\n</div>\n</div>\n<a class=\"anchor\" id=\"aaeb2860d7301485d40d9f0d9bb868fbb\"></a><!-- doxytag: member=\"sp_offline_sync_status::done_tracks\" ref=\"aaeb2860d7301485d40d9f0d9bb868fbb\" args=\"\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\">int <a class=\"el\" href=\"structsp__offline__sync__status.html#aaeb2860d7301485d40d9f0d9bb868fbb\">sp_offline_sync_status::done_tracks</a></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Done tracks/bytes is things marked for sync that existed on device before current sync operation </p>\n\n</div>\n</div>\n<a class=\"anchor\" id=\"aa5002b69e3826edc285d19eb7ca0f582\"></a><!-- doxytag: member=\"sp_offline_sync_status::error_tracks\" ref=\"aa5002b69e3826edc285d19eb7ca0f582\" args=\"\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\">int <a class=\"el\" href=\"structsp__offline__sync__status.html#aa5002b69e3826edc285d19eb7ca0f582\">sp_offline_sync_status::error_tracks</a></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>A track is counted as error when something goes wrong while syncing the track </p>\n\n</div>\n</div>\n<a class=\"anchor\" id=\"a44a8a719c66266763ed184b575abce61\"></a><!-- doxytag: member=\"sp_offline_sync_status::queued_tracks\" ref=\"a44a8a719c66266763ed184b575abce61\" args=\"\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\">int <a class=\"el\" href=\"structsp__offline__sync__status.html#a44a8a719c66266763ed184b575abce61\">sp_offline_sync_status::queued_tracks</a></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Queued tracks/bytes is things left to sync in current sync operation </p>\n\n</div>\n</div>\n<a class=\"anchor\" id=\"a5a2a99fdb8eeb38b3c73a44c6df68d06\"></a><!-- doxytag: member=\"sp_offline_sync_status::syncing\" ref=\"a5a2a99fdb8eeb38b3c73a44c6df68d06\" args=\"\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\">bool <a class=\"el\" href=\"structsp__offline__sync__status.html#a5a2a99fdb8eeb38b3c73a44c6df68d06\">sp_offline_sync_status::syncing</a></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Set if sync operation is in progress </p>\n\n</div>\n</div>\n<a class=\"anchor\" id=\"aa56788dbda2c99047cc79282caf3ffd6\"></a><!-- doxytag: member=\"sp_offline_sync_status::willnotcopy_tracks\" ref=\"aa56788dbda2c99047cc79282caf3ffd6\" args=\"\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\">int <a class=\"el\" href=\"structsp__offline__sync__status.html#aa56788dbda2c99047cc79282caf3ffd6\">sp_offline_sync_status::willnotcopy_tracks</a></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Tracks that are marked as synced but will not be copied (for various reasons) </p>\n\n</div>\n</div>\n<hr/>The documentation for this struct was generated from the following file:<ul>\n<li><a class=\"el\" href=\"api_8h.html\">api.h</a></li>\n</ul>\n</div>\n<hr size=\"1\"><address style=\"text-align: right;\"><small>\nGenerated on Wed Jun 13 2012 14:22:40.<br>\nCopyright &copy; 2006&ndash;2012 Spotify Ltd</small></address>\n</body>\n</html>\n"
  },
  {
    "path": "libspotify/docs/html/structsp__playlist__callbacks.html",
    "content": "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\n<html xmlns=\"http://www.w3.org/1999/xhtml\">\n<head>\n<meta http-equiv=\"Content-Type\" content=\"text/xhtml;charset=UTF-8\"/>\n<title>libspotify: sp_playlist_callbacks Struct Reference</title>\n<link href=\"tabs.css\" rel=\"stylesheet\" type=\"text/css\"/>\n<link href=\"doxygen.css\" rel=\"stylesheet\" type=\"text/css\"/>\n</head>\n<body>\n<!-- Generated by Doxygen 1.7.1 -->\n<div class=\"navigation\" id=\"top\">\n  <div class=\"tabs\">\n    <ul class=\"tablist\">\n      <li><a href=\"index.html\"><span>Main&nbsp;Page</span></a></li>\n      <li><a href=\"modules.html\"><span>Modules</span></a></li>\n      <li class=\"current\"><a href=\"annotated.html\"><span>Data&nbsp;Structures</span></a></li>\n      <li><a href=\"files.html\"><span>Files</span></a></li>\n      <li><a href=\"examples.html\"><span>Examples</span></a></li>\n    </ul>\n  </div>\n  <div class=\"tabs2\">\n    <ul class=\"tablist\">\n      <li><a href=\"annotated.html\"><span>Data&nbsp;Structures</span></a></li>\n      <li><a href=\"functions.html\"><span>Data&nbsp;Fields</span></a></li>\n    </ul>\n  </div>\n</div>\n<div class=\"header\">\n  <div class=\"summary\">\n<a href=\"#pub-attribs\">Data Fields</a>  </div>\n  <div class=\"headertitle\">\n<h1>sp_playlist_callbacks Struct Reference<br/>\n<small>\n[<a class=\"el\" href=\"group__playlist.html\">Playlist subsystem</a>]</small>\n</h1>  </div>\n</div>\n<div class=\"contents\">\n<!-- doxytag: class=\"sp_playlist_callbacks\" -->\n<p><code>#include &lt;api.h&gt;</code></p>\n<table class=\"memberdecls\">\n<tr><td colspan=\"2\"><h2><a name=\"pub-attribs\"></a>\nData Fields</h2></td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">void(*&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"structsp__playlist__callbacks.html#a16c3e5758f8f73f5900de4b88424f85e\">tracks_added</a> )(<a class=\"el\" href=\"group__types.html#ga1bcf54cbc117a20ab2c15e59eb3a8174\">sp_playlist</a> *pl, <a class=\"el\" href=\"group__types.html#ga47bbd2262f0c8b5d7147af7d62198e48\">sp_track</a> *const *tracks, int num_tracks, int position, void *userdata)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">void(*&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"structsp__playlist__callbacks.html#a8f7decf111d725363c968ae4e7b15795\">tracks_removed</a> )(<a class=\"el\" href=\"group__types.html#ga1bcf54cbc117a20ab2c15e59eb3a8174\">sp_playlist</a> *pl, const int *tracks, int num_tracks, void *userdata)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">void(*&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"structsp__playlist__callbacks.html#ac3d51200f7a813cce810561132dba4e9\">tracks_moved</a> )(<a class=\"el\" href=\"group__types.html#ga1bcf54cbc117a20ab2c15e59eb3a8174\">sp_playlist</a> *pl, const int *tracks, int num_tracks, int new_position, void *userdata)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">void(*&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"structsp__playlist__callbacks.html#a25e98e4355cf2d3503c7ac708c8104cf\">playlist_renamed</a> )(<a class=\"el\" href=\"group__types.html#ga1bcf54cbc117a20ab2c15e59eb3a8174\">sp_playlist</a> *pl, void *userdata)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">void(*&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"structsp__playlist__callbacks.html#a7ff55580625a755b196336a551d210d4\">playlist_state_changed</a> )(<a class=\"el\" href=\"group__types.html#ga1bcf54cbc117a20ab2c15e59eb3a8174\">sp_playlist</a> *pl, void *userdata)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">void(*&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"structsp__playlist__callbacks.html#ab07f7eb6c283523afb37d683932b62d4\">playlist_update_in_progress</a> )(<a class=\"el\" href=\"group__types.html#ga1bcf54cbc117a20ab2c15e59eb3a8174\">sp_playlist</a> *pl, bool done, void *userdata)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">void(*&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"structsp__playlist__callbacks.html#a0de3ae5463973647c114d5fdc85ade87\">playlist_metadata_updated</a> )(<a class=\"el\" href=\"group__types.html#ga1bcf54cbc117a20ab2c15e59eb3a8174\">sp_playlist</a> *pl, void *userdata)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">void(*&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"structsp__playlist__callbacks.html#a152a3b599f22f4040ff0581c6927d12e\">track_created_changed</a> )(<a class=\"el\" href=\"group__types.html#ga1bcf54cbc117a20ab2c15e59eb3a8174\">sp_playlist</a> *pl, int position, <a class=\"el\" href=\"group__types.html#gaed2dbaa1eebd6752f76613daad9158bc\">sp_user</a> *user, int when, void *userdata)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">void(*&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"structsp__playlist__callbacks.html#ab78eaf42523f53bb5931eaff8dcdea8b\">track_seen_changed</a> )(<a class=\"el\" href=\"group__types.html#ga1bcf54cbc117a20ab2c15e59eb3a8174\">sp_playlist</a> *pl, int position, bool seen, void *userdata)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">void(*&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"structsp__playlist__callbacks.html#a07d1ebf29e1ba1f8b10c7a8c5e209f41\">description_changed</a> )(<a class=\"el\" href=\"group__types.html#ga1bcf54cbc117a20ab2c15e59eb3a8174\">sp_playlist</a> *pl, const char *desc, void *userdata)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">void(*&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"structsp__playlist__callbacks.html#a910203945dcd26b02b390d5413e4f5dd\">image_changed</a> )(<a class=\"el\" href=\"group__types.html#ga1bcf54cbc117a20ab2c15e59eb3a8174\">sp_playlist</a> *pl, const byte *image, void *userdata)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">void(*&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"structsp__playlist__callbacks.html#ad26fb637a16ed0590bdf7936dfcad82d\">track_message_changed</a> )(<a class=\"el\" href=\"group__types.html#ga1bcf54cbc117a20ab2c15e59eb3a8174\">sp_playlist</a> *pl, int position, const char *message, void *userdata)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">void(*&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"structsp__playlist__callbacks.html#ae33cb7f8ebc9eac186c9f22272d093c3\">subscribers_changed</a> )(<a class=\"el\" href=\"group__types.html#ga1bcf54cbc117a20ab2c15e59eb3a8174\">sp_playlist</a> *pl, void *userdata)</td></tr>\n</table>\n<hr/><a name=\"_details\"></a><h2>Detailed Description</h2>\n<p>Playlist callbacks</p>\n<p>Used to get notifications when playlists are updated. If some callbacks should not be of interest, set them to NULL. </p>\n<dl><dt><b>Examples: </b></dt><dd>\n<p><a class=\"el\" href=\"browse_8c-example.html#_a0\">browse.c</a>, and <a class=\"el\" href=\"jukebox_8c-example.html#_a9\">jukebox.c</a>.</p>\n</dd>\n</dl><hr/><h2>Field Documentation</h2>\n<a class=\"anchor\" id=\"a07d1ebf29e1ba1f8b10c7a8c5e209f41\"></a><!-- doxytag: member=\"sp_playlist_callbacks::description_changed\" ref=\"a07d1ebf29e1ba1f8b10c7a8c5e209f41\" args=\")(sp_playlist *pl, const char *desc, void *userdata)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\">void( * <a class=\"el\" href=\"structsp__playlist__callbacks.html#a07d1ebf29e1ba1f8b10c7a8c5e209f41\">sp_playlist_callbacks::description_changed</a>)(<a class=\"el\" href=\"group__types.html#ga1bcf54cbc117a20ab2c15e59eb3a8174\">sp_playlist</a> *pl, const char *desc, void *userdata)</td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Called when playlist description has changed</p>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>pl</em>&nbsp;</td><td>Playlist object </td></tr>\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>desc</em>&nbsp;</td><td>New description </td></tr>\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>userdata</em>&nbsp;</td><td>Userdata passed to <a class=\"el\" href=\"group__playlist.html#gab15fca12d387c69b4998a4d2b48e5b32\">sp_playlist_add_callbacks()</a> </td></tr>\n  </table>\n  </dd>\n</dl>\n\n</div>\n</div>\n<a class=\"anchor\" id=\"a910203945dcd26b02b390d5413e4f5dd\"></a><!-- doxytag: member=\"sp_playlist_callbacks::image_changed\" ref=\"a910203945dcd26b02b390d5413e4f5dd\" args=\")(sp_playlist *pl, const byte *image, void *userdata)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\">void( * <a class=\"el\" href=\"structsp__playlist__callbacks.html#a910203945dcd26b02b390d5413e4f5dd\">sp_playlist_callbacks::image_changed</a>)(<a class=\"el\" href=\"group__types.html#ga1bcf54cbc117a20ab2c15e59eb3a8174\">sp_playlist</a> *pl, const byte *image, void *userdata)</td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Called when playlist image has changed</p>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>pl</em>&nbsp;</td><td>Playlist object </td></tr>\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>image</em>&nbsp;</td><td>New image </td></tr>\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>userdata</em>&nbsp;</td><td>Userdata passed to <a class=\"el\" href=\"group__playlist.html#gab15fca12d387c69b4998a4d2b48e5b32\">sp_playlist_add_callbacks()</a> </td></tr>\n  </table>\n  </dd>\n</dl>\n\n</div>\n</div>\n<a class=\"anchor\" id=\"a0de3ae5463973647c114d5fdc85ade87\"></a><!-- doxytag: member=\"sp_playlist_callbacks::playlist_metadata_updated\" ref=\"a0de3ae5463973647c114d5fdc85ade87\" args=\")(sp_playlist *pl, void *userdata)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\">void( * <a class=\"el\" href=\"structsp__playlist__callbacks.html#a0de3ae5463973647c114d5fdc85ade87\">sp_playlist_callbacks::playlist_metadata_updated</a>)(<a class=\"el\" href=\"group__types.html#ga1bcf54cbc117a20ab2c15e59eb3a8174\">sp_playlist</a> *pl, void *userdata)</td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Called when metadata for one or more tracks in a playlist has been updated.</p>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>pl</em>&nbsp;</td><td>Playlist object </td></tr>\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>userdata</em>&nbsp;</td><td>Userdata passed to <a class=\"el\" href=\"group__playlist.html#gab15fca12d387c69b4998a4d2b48e5b32\">sp_playlist_add_callbacks()</a> </td></tr>\n  </table>\n  </dd>\n</dl>\n\n</div>\n</div>\n<a class=\"anchor\" id=\"a25e98e4355cf2d3503c7ac708c8104cf\"></a><!-- doxytag: member=\"sp_playlist_callbacks::playlist_renamed\" ref=\"a25e98e4355cf2d3503c7ac708c8104cf\" args=\")(sp_playlist *pl, void *userdata)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\">void( * <a class=\"el\" href=\"structsp__playlist__callbacks.html#a25e98e4355cf2d3503c7ac708c8104cf\">sp_playlist_callbacks::playlist_renamed</a>)(<a class=\"el\" href=\"group__types.html#ga1bcf54cbc117a20ab2c15e59eb3a8174\">sp_playlist</a> *pl, void *userdata)</td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Called when a playlist has been renamed. <a class=\"el\" href=\"group__playlist.html#ga61b7e33cc1aedb4e31a2af75ae0ac8cc\">sp_playlist_name()</a> can be used to find out the new name</p>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>pl</em>&nbsp;</td><td>Playlist object </td></tr>\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>userdata</em>&nbsp;</td><td>Userdata passed to <a class=\"el\" href=\"group__playlist.html#gab15fca12d387c69b4998a4d2b48e5b32\">sp_playlist_add_callbacks()</a> </td></tr>\n  </table>\n  </dd>\n</dl>\n\n</div>\n</div>\n<a class=\"anchor\" id=\"a7ff55580625a755b196336a551d210d4\"></a><!-- doxytag: member=\"sp_playlist_callbacks::playlist_state_changed\" ref=\"a7ff55580625a755b196336a551d210d4\" args=\")(sp_playlist *pl, void *userdata)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\">void( * <a class=\"el\" href=\"structsp__playlist__callbacks.html#a7ff55580625a755b196336a551d210d4\">sp_playlist_callbacks::playlist_state_changed</a>)(<a class=\"el\" href=\"group__types.html#ga1bcf54cbc117a20ab2c15e59eb3a8174\">sp_playlist</a> *pl, void *userdata)</td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Called when state changed for a playlist.</p>\n<p>There are three states that trigger this callback:</p>\n<ul>\n<li>Collaboration for this playlist has been turned on or off</li>\n<li>The playlist started having pending changes, or all pending changes have now been committed</li>\n<li>The playlist started loading, or finished loading</li>\n</ul>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>pl</em>&nbsp;</td><td>Playlist object </td></tr>\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>userdata</em>&nbsp;</td><td>Userdata passed to <a class=\"el\" href=\"group__playlist.html#gab15fca12d387c69b4998a4d2b48e5b32\">sp_playlist_add_callbacks()</a> </td></tr>\n  </table>\n  </dd>\n</dl>\n<dl class=\"see\"><dt><b>See also:</b></dt><dd><a class=\"el\" href=\"group__playlist.html#ga8ad160f654f02f13690568070dd57353\">sp_playlist_is_collaborative</a> </dd>\n<dd>\n<a class=\"el\" href=\"group__playlist.html#gaf0e39b5969259d10625eb398af0f3f43\">sp_playlist_has_pending_changes</a> </dd>\n<dd>\n<a class=\"el\" href=\"group__playlist.html#gaee8ea6c07dfdca3397e27b278fa4870a\">sp_playlist_is_loaded</a> </dd></dl>\n\n</div>\n</div>\n<a class=\"anchor\" id=\"ab07f7eb6c283523afb37d683932b62d4\"></a><!-- doxytag: member=\"sp_playlist_callbacks::playlist_update_in_progress\" ref=\"ab07f7eb6c283523afb37d683932b62d4\" args=\")(sp_playlist *pl, bool done, void *userdata)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\">void( * <a class=\"el\" href=\"structsp__playlist__callbacks.html#ab07f7eb6c283523afb37d683932b62d4\">sp_playlist_callbacks::playlist_update_in_progress</a>)(<a class=\"el\" href=\"group__types.html#ga1bcf54cbc117a20ab2c15e59eb3a8174\">sp_playlist</a> *pl, bool done, void *userdata)</td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Called when a playlist is updating or is done updating</p>\n<p>This is called before and after a series of changes are applied to the playlist. It allows e.g. the user interface to defer updating until the entire operation is complete.</p>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>pl</em>&nbsp;</td><td>Playlist object </td></tr>\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>done</em>&nbsp;</td><td>True iff the update is completed </td></tr>\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>userdata</em>&nbsp;</td><td>Userdata passed to <a class=\"el\" href=\"group__playlist.html#gab15fca12d387c69b4998a4d2b48e5b32\">sp_playlist_add_callbacks()</a> </td></tr>\n  </table>\n  </dd>\n</dl>\n\n</div>\n</div>\n<a class=\"anchor\" id=\"ae33cb7f8ebc9eac186c9f22272d093c3\"></a><!-- doxytag: member=\"sp_playlist_callbacks::subscribers_changed\" ref=\"ae33cb7f8ebc9eac186c9f22272d093c3\" args=\")(sp_playlist *pl, void *userdata)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\">void( * <a class=\"el\" href=\"structsp__playlist__callbacks.html#ae33cb7f8ebc9eac186c9f22272d093c3\">sp_playlist_callbacks::subscribers_changed</a>)(<a class=\"el\" href=\"group__types.html#ga1bcf54cbc117a20ab2c15e59eb3a8174\">sp_playlist</a> *pl, void *userdata)</td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Called when playlist subscribers changes (count or list of names)</p>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>pl</em>&nbsp;</td><td>Playlist object </td></tr>\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>userdata</em>&nbsp;</td><td>Userdata passed to <a class=\"el\" href=\"group__playlist.html#gab15fca12d387c69b4998a4d2b48e5b32\">sp_playlist_add_callbacks()</a> </td></tr>\n  </table>\n  </dd>\n</dl>\n\n</div>\n</div>\n<a class=\"anchor\" id=\"a152a3b599f22f4040ff0581c6927d12e\"></a><!-- doxytag: member=\"sp_playlist_callbacks::track_created_changed\" ref=\"a152a3b599f22f4040ff0581c6927d12e\" args=\")(sp_playlist *pl, int position, sp_user *user, int when, void *userdata)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\">void( * <a class=\"el\" href=\"structsp__playlist__callbacks.html#a152a3b599f22f4040ff0581c6927d12e\">sp_playlist_callbacks::track_created_changed</a>)(<a class=\"el\" href=\"group__types.html#ga1bcf54cbc117a20ab2c15e59eb3a8174\">sp_playlist</a> *pl, int position, <a class=\"el\" href=\"group__types.html#gaed2dbaa1eebd6752f76613daad9158bc\">sp_user</a> *user, int when, void *userdata)</td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Called when create time and/or creator for a playlist entry changes</p>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>pl</em>&nbsp;</td><td>Playlist object </td></tr>\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>position</em>&nbsp;</td><td>Position in playlist </td></tr>\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>user</em>&nbsp;</td><td>User object </td></tr>\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>time</em>&nbsp;</td><td>When entry was created, seconds since the unix epoch. </td></tr>\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>userdata</em>&nbsp;</td><td>Userdata passed to <a class=\"el\" href=\"group__playlist.html#gab15fca12d387c69b4998a4d2b48e5b32\">sp_playlist_add_callbacks()</a> </td></tr>\n  </table>\n  </dd>\n</dl>\n\n</div>\n</div>\n<a class=\"anchor\" id=\"ad26fb637a16ed0590bdf7936dfcad82d\"></a><!-- doxytag: member=\"sp_playlist_callbacks::track_message_changed\" ref=\"ad26fb637a16ed0590bdf7936dfcad82d\" args=\")(sp_playlist *pl, int position, const char *message, void *userdata)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\">void( * <a class=\"el\" href=\"structsp__playlist__callbacks.html#ad26fb637a16ed0590bdf7936dfcad82d\">sp_playlist_callbacks::track_message_changed</a>)(<a class=\"el\" href=\"group__types.html#ga1bcf54cbc117a20ab2c15e59eb3a8174\">sp_playlist</a> *pl, int position, const char *message, void *userdata)</td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Called when message attribute for a playlist entry changes.</p>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>pl</em>&nbsp;</td><td>Playlist object </td></tr>\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>position</em>&nbsp;</td><td>Position in playlist </td></tr>\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>message</em>&nbsp;</td><td>UTF-8 encoded message </td></tr>\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>userdata</em>&nbsp;</td><td>Userdata passed to <a class=\"el\" href=\"group__playlist.html#gab15fca12d387c69b4998a4d2b48e5b32\">sp_playlist_add_callbacks()</a> </td></tr>\n  </table>\n  </dd>\n</dl>\n\n</div>\n</div>\n<a class=\"anchor\" id=\"ab78eaf42523f53bb5931eaff8dcdea8b\"></a><!-- doxytag: member=\"sp_playlist_callbacks::track_seen_changed\" ref=\"ab78eaf42523f53bb5931eaff8dcdea8b\" args=\")(sp_playlist *pl, int position, bool seen, void *userdata)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\">void( * <a class=\"el\" href=\"structsp__playlist__callbacks.html#ab78eaf42523f53bb5931eaff8dcdea8b\">sp_playlist_callbacks::track_seen_changed</a>)(<a class=\"el\" href=\"group__types.html#ga1bcf54cbc117a20ab2c15e59eb3a8174\">sp_playlist</a> *pl, int position, bool seen, void *userdata)</td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Called when seen attribute for a playlist entry changes.</p>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>pl</em>&nbsp;</td><td>Playlist object </td></tr>\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>position</em>&nbsp;</td><td>Position in playlist </td></tr>\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>seen</em>&nbsp;</td><td>Set if entry it marked as seen </td></tr>\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>userdata</em>&nbsp;</td><td>Userdata passed to <a class=\"el\" href=\"group__playlist.html#gab15fca12d387c69b4998a4d2b48e5b32\">sp_playlist_add_callbacks()</a> </td></tr>\n  </table>\n  </dd>\n</dl>\n\n</div>\n</div>\n<a class=\"anchor\" id=\"a16c3e5758f8f73f5900de4b88424f85e\"></a><!-- doxytag: member=\"sp_playlist_callbacks::tracks_added\" ref=\"a16c3e5758f8f73f5900de4b88424f85e\" args=\")(sp_playlist *pl, sp_track *const *tracks, int num_tracks, int position, void *userdata)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\">void( * <a class=\"el\" href=\"structsp__playlist__callbacks.html#a16c3e5758f8f73f5900de4b88424f85e\">sp_playlist_callbacks::tracks_added</a>)(<a class=\"el\" href=\"group__types.html#ga1bcf54cbc117a20ab2c15e59eb3a8174\">sp_playlist</a> *pl, <a class=\"el\" href=\"group__types.html#ga47bbd2262f0c8b5d7147af7d62198e48\">sp_track</a> *const *tracks, int num_tracks, int position, void *userdata)</td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Called when one or more tracks have been added to a playlist</p>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>pl</em>&nbsp;</td><td>Playlist object </td></tr>\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>tracks</em>&nbsp;</td><td>Array of pointers to track objects </td></tr>\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>num_tracks</em>&nbsp;</td><td>Number of entries in <code>tracks</code> </td></tr>\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>position</em>&nbsp;</td><td>Position in the playlist for the first track. </td></tr>\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>userdata</em>&nbsp;</td><td>Userdata passed to <a class=\"el\" href=\"group__playlist.html#gab15fca12d387c69b4998a4d2b48e5b32\">sp_playlist_add_callbacks()</a> </td></tr>\n  </table>\n  </dd>\n</dl>\n\n</div>\n</div>\n<a class=\"anchor\" id=\"ac3d51200f7a813cce810561132dba4e9\"></a><!-- doxytag: member=\"sp_playlist_callbacks::tracks_moved\" ref=\"ac3d51200f7a813cce810561132dba4e9\" args=\")(sp_playlist *pl, const int *tracks, int num_tracks, int new_position, void *userdata)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\">void( * <a class=\"el\" href=\"structsp__playlist__callbacks.html#ac3d51200f7a813cce810561132dba4e9\">sp_playlist_callbacks::tracks_moved</a>)(<a class=\"el\" href=\"group__types.html#ga1bcf54cbc117a20ab2c15e59eb3a8174\">sp_playlist</a> *pl, const int *tracks, int num_tracks, int new_position, void *userdata)</td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Called when one or more tracks have been moved within a playlist</p>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>pl</em>&nbsp;</td><td>Playlist object </td></tr>\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>tracks</em>&nbsp;</td><td>Array of positions representing the tracks that were moved </td></tr>\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>num_tracks</em>&nbsp;</td><td>Number of entries in <code>tracks</code> </td></tr>\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>position</em>&nbsp;</td><td>New position in the playlist for the first track. </td></tr>\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>userdata</em>&nbsp;</td><td>Userdata passed to <a class=\"el\" href=\"group__playlist.html#gab15fca12d387c69b4998a4d2b48e5b32\">sp_playlist_add_callbacks()</a> </td></tr>\n  </table>\n  </dd>\n</dl>\n\n</div>\n</div>\n<a class=\"anchor\" id=\"a8f7decf111d725363c968ae4e7b15795\"></a><!-- doxytag: member=\"sp_playlist_callbacks::tracks_removed\" ref=\"a8f7decf111d725363c968ae4e7b15795\" args=\")(sp_playlist *pl, const int *tracks, int num_tracks, void *userdata)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\">void( * <a class=\"el\" href=\"structsp__playlist__callbacks.html#a8f7decf111d725363c968ae4e7b15795\">sp_playlist_callbacks::tracks_removed</a>)(<a class=\"el\" href=\"group__types.html#ga1bcf54cbc117a20ab2c15e59eb3a8174\">sp_playlist</a> *pl, const int *tracks, int num_tracks, void *userdata)</td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Called when one or more tracks have been removed from a playlist</p>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>pl</em>&nbsp;</td><td>Playlist object </td></tr>\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>tracks</em>&nbsp;</td><td>Array of positions representing the tracks that were removed </td></tr>\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>num_tracks</em>&nbsp;</td><td>Number of entries in <code>tracks</code> </td></tr>\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>userdata</em>&nbsp;</td><td>Userdata passed to <a class=\"el\" href=\"group__playlist.html#gab15fca12d387c69b4998a4d2b48e5b32\">sp_playlist_add_callbacks()</a> </td></tr>\n  </table>\n  </dd>\n</dl>\n\n</div>\n</div>\n<hr/>The documentation for this struct was generated from the following file:<ul>\n<li><a class=\"el\" href=\"api_8h.html\">api.h</a></li>\n</ul>\n</div>\n<hr size=\"1\"><address style=\"text-align: right;\"><small>\nGenerated on Wed Jun 13 2012 14:22:40.<br>\nCopyright &copy; 2006&ndash;2012 Spotify Ltd</small></address>\n</body>\n</html>\n"
  },
  {
    "path": "libspotify/docs/html/structsp__playlistcontainer__callbacks.html",
    "content": "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\n<html xmlns=\"http://www.w3.org/1999/xhtml\">\n<head>\n<meta http-equiv=\"Content-Type\" content=\"text/xhtml;charset=UTF-8\"/>\n<title>libspotify: sp_playlistcontainer_callbacks Struct Reference</title>\n<link href=\"tabs.css\" rel=\"stylesheet\" type=\"text/css\"/>\n<link href=\"doxygen.css\" rel=\"stylesheet\" type=\"text/css\"/>\n</head>\n<body>\n<!-- Generated by Doxygen 1.7.1 -->\n<div class=\"navigation\" id=\"top\">\n  <div class=\"tabs\">\n    <ul class=\"tablist\">\n      <li><a href=\"index.html\"><span>Main&nbsp;Page</span></a></li>\n      <li><a href=\"modules.html\"><span>Modules</span></a></li>\n      <li class=\"current\"><a href=\"annotated.html\"><span>Data&nbsp;Structures</span></a></li>\n      <li><a href=\"files.html\"><span>Files</span></a></li>\n      <li><a href=\"examples.html\"><span>Examples</span></a></li>\n    </ul>\n  </div>\n  <div class=\"tabs2\">\n    <ul class=\"tablist\">\n      <li><a href=\"annotated.html\"><span>Data&nbsp;Structures</span></a></li>\n      <li><a href=\"functions.html\"><span>Data&nbsp;Fields</span></a></li>\n    </ul>\n  </div>\n</div>\n<div class=\"header\">\n  <div class=\"summary\">\n<a href=\"#pub-attribs\">Data Fields</a>  </div>\n  <div class=\"headertitle\">\n<h1>sp_playlistcontainer_callbacks Struct Reference<br/>\n<small>\n[<a class=\"el\" href=\"group__playlist.html\">Playlist subsystem</a>]</small>\n</h1>  </div>\n</div>\n<div class=\"contents\">\n<!-- doxytag: class=\"sp_playlistcontainer_callbacks\" -->\n<p><code>#include &lt;api.h&gt;</code></p>\n<table class=\"memberdecls\">\n<tr><td colspan=\"2\"><h2><a name=\"pub-attribs\"></a>\nData Fields</h2></td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">void(*&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"structsp__playlistcontainer__callbacks.html#ab1ba98e60fe050aeda8edc95166dd6fe\">playlist_added</a> )(<a class=\"el\" href=\"group__types.html#ga45a2febbe167483e48dab8d606d462d7\">sp_playlistcontainer</a> *pc, <a class=\"el\" href=\"group__types.html#ga1bcf54cbc117a20ab2c15e59eb3a8174\">sp_playlist</a> *playlist, int position, void *userdata)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">void(*&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"structsp__playlistcontainer__callbacks.html#ad49b8c0f44f6c05e4ab3562b023f0928\">playlist_removed</a> )(<a class=\"el\" href=\"group__types.html#ga45a2febbe167483e48dab8d606d462d7\">sp_playlistcontainer</a> *pc, <a class=\"el\" href=\"group__types.html#ga1bcf54cbc117a20ab2c15e59eb3a8174\">sp_playlist</a> *playlist, int position, void *userdata)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">void(*&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"structsp__playlistcontainer__callbacks.html#a64889a47ae2023e21be1ca4a8024c663\">playlist_moved</a> )(<a class=\"el\" href=\"group__types.html#ga45a2febbe167483e48dab8d606d462d7\">sp_playlistcontainer</a> *pc, <a class=\"el\" href=\"group__types.html#ga1bcf54cbc117a20ab2c15e59eb3a8174\">sp_playlist</a> *playlist, int position, int new_position, void *userdata)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">void(*&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"structsp__playlistcontainer__callbacks.html#a8a0c301dd9cf90cccb4657a7d65c61b1\">container_loaded</a> )(<a class=\"el\" href=\"group__types.html#ga45a2febbe167483e48dab8d606d462d7\">sp_playlistcontainer</a> *pc, void *userdata)</td></tr>\n</table>\n<hr/><a name=\"_details\"></a><h2>Detailed Description</h2>\n<p>Playlist container callbacks. If some callbacks should not be of interest, set them to NULL.</p>\n<dl class=\"see\"><dt><b>See also:</b></dt><dd><a class=\"el\" href=\"group__playlist.html#ga1976cb49c391cdd2dbe7c40d1bc71570\">sp_playlistcontainer_add_callbacks</a> </dd>\n<dd>\n<a class=\"el\" href=\"group__playlist.html#gafb5242b8f0f9964cec29d32f4d6c1164\">sp_playlistcontainer_remove_callbacks</a> </dd></dl>\n<dl><dt><b>Examples: </b></dt><dd>\n<p><a class=\"el\" href=\"jukebox_8c-example.html#_a13\">jukebox.c</a>.</p>\n</dd>\n</dl><hr/><h2>Field Documentation</h2>\n<a class=\"anchor\" id=\"a8a0c301dd9cf90cccb4657a7d65c61b1\"></a><!-- doxytag: member=\"sp_playlistcontainer_callbacks::container_loaded\" ref=\"a8a0c301dd9cf90cccb4657a7d65c61b1\" args=\")(sp_playlistcontainer *pc, void *userdata)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\">void( * <a class=\"el\" href=\"structsp__playlistcontainer__callbacks.html#a8a0c301dd9cf90cccb4657a7d65c61b1\">sp_playlistcontainer_callbacks::container_loaded</a>)(<a class=\"el\" href=\"group__types.html#ga45a2febbe167483e48dab8d606d462d7\">sp_playlistcontainer</a> *pc, void *userdata)</td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Called when the playlist container is loaded</p>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>pc</em>&nbsp;</td><td>Playlist container </td></tr>\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>userdata</em>&nbsp;</td><td>Userdata as set in <a class=\"el\" href=\"group__playlist.html#ga1976cb49c391cdd2dbe7c40d1bc71570\">sp_playlistcontainer_add_callbacks()</a> </td></tr>\n  </table>\n  </dd>\n</dl>\n\n</div>\n</div>\n<a class=\"anchor\" id=\"ab1ba98e60fe050aeda8edc95166dd6fe\"></a><!-- doxytag: member=\"sp_playlistcontainer_callbacks::playlist_added\" ref=\"ab1ba98e60fe050aeda8edc95166dd6fe\" args=\")(sp_playlistcontainer *pc, sp_playlist *playlist, int position, void *userdata)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\">void( * <a class=\"el\" href=\"structsp__playlistcontainer__callbacks.html#ab1ba98e60fe050aeda8edc95166dd6fe\">sp_playlistcontainer_callbacks::playlist_added</a>)(<a class=\"el\" href=\"group__types.html#ga45a2febbe167483e48dab8d606d462d7\">sp_playlistcontainer</a> *pc, <a class=\"el\" href=\"group__types.html#ga1bcf54cbc117a20ab2c15e59eb3a8174\">sp_playlist</a> *playlist, int position, void *userdata)</td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Called when a new playlist has been added to the playlist container.</p>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>pc</em>&nbsp;</td><td>Playlist container </td></tr>\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>playlist</em>&nbsp;</td><td>Playlist object. </td></tr>\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>position</em>&nbsp;</td><td>Position in list </td></tr>\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>userdata</em>&nbsp;</td><td>Userdata as set in <a class=\"el\" href=\"group__playlist.html#ga1976cb49c391cdd2dbe7c40d1bc71570\">sp_playlistcontainer_add_callbacks()</a> </td></tr>\n  </table>\n  </dd>\n</dl>\n\n</div>\n</div>\n<a class=\"anchor\" id=\"a64889a47ae2023e21be1ca4a8024c663\"></a><!-- doxytag: member=\"sp_playlistcontainer_callbacks::playlist_moved\" ref=\"a64889a47ae2023e21be1ca4a8024c663\" args=\")(sp_playlistcontainer *pc, sp_playlist *playlist, int position, int new_position, void *userdata)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\">void( * <a class=\"el\" href=\"structsp__playlistcontainer__callbacks.html#a64889a47ae2023e21be1ca4a8024c663\">sp_playlistcontainer_callbacks::playlist_moved</a>)(<a class=\"el\" href=\"group__types.html#ga45a2febbe167483e48dab8d606d462d7\">sp_playlistcontainer</a> *pc, <a class=\"el\" href=\"group__types.html#ga1bcf54cbc117a20ab2c15e59eb3a8174\">sp_playlist</a> *playlist, int position, int new_position, void *userdata)</td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Called when a playlist has been moved in the playlist container</p>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>pc</em>&nbsp;</td><td>Playlist container </td></tr>\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>playlist</em>&nbsp;</td><td>Playlist object. </td></tr>\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>position</em>&nbsp;</td><td>Previous position in playlist container list </td></tr>\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>new_position</em>&nbsp;</td><td>New position in playlist container list </td></tr>\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>userdata</em>&nbsp;</td><td>Userdata as set in <a class=\"el\" href=\"group__playlist.html#ga1976cb49c391cdd2dbe7c40d1bc71570\">sp_playlistcontainer_add_callbacks()</a> </td></tr>\n  </table>\n  </dd>\n</dl>\n\n</div>\n</div>\n<a class=\"anchor\" id=\"ad49b8c0f44f6c05e4ab3562b023f0928\"></a><!-- doxytag: member=\"sp_playlistcontainer_callbacks::playlist_removed\" ref=\"ad49b8c0f44f6c05e4ab3562b023f0928\" args=\")(sp_playlistcontainer *pc, sp_playlist *playlist, int position, void *userdata)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\">void( * <a class=\"el\" href=\"structsp__playlistcontainer__callbacks.html#ad49b8c0f44f6c05e4ab3562b023f0928\">sp_playlistcontainer_callbacks::playlist_removed</a>)(<a class=\"el\" href=\"group__types.html#ga45a2febbe167483e48dab8d606d462d7\">sp_playlistcontainer</a> *pc, <a class=\"el\" href=\"group__types.html#ga1bcf54cbc117a20ab2c15e59eb3a8174\">sp_playlist</a> *playlist, int position, void *userdata)</td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Called when a new playlist has been removed from playlist container</p>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>pc</em>&nbsp;</td><td>Playlist container </td></tr>\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>playlist</em>&nbsp;</td><td>Playlist object. </td></tr>\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>position</em>&nbsp;</td><td>Position in list </td></tr>\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>userdata</em>&nbsp;</td><td>Userdata as set in <a class=\"el\" href=\"group__playlist.html#ga1976cb49c391cdd2dbe7c40d1bc71570\">sp_playlistcontainer_add_callbacks()</a> </td></tr>\n  </table>\n  </dd>\n</dl>\n\n</div>\n</div>\n<hr/>The documentation for this struct was generated from the following file:<ul>\n<li><a class=\"el\" href=\"api_8h.html\">api.h</a></li>\n</ul>\n</div>\n<hr size=\"1\"><address style=\"text-align: right;\"><small>\nGenerated on Wed Jun 13 2012 14:22:40.<br>\nCopyright &copy; 2006&ndash;2012 Spotify Ltd</small></address>\n</body>\n</html>\n"
  },
  {
    "path": "libspotify/docs/html/structsp__session__callbacks.html",
    "content": "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\n<html xmlns=\"http://www.w3.org/1999/xhtml\">\n<head>\n<meta http-equiv=\"Content-Type\" content=\"text/xhtml;charset=UTF-8\"/>\n<title>libspotify: sp_session_callbacks Struct Reference</title>\n<link href=\"tabs.css\" rel=\"stylesheet\" type=\"text/css\"/>\n<link href=\"doxygen.css\" rel=\"stylesheet\" type=\"text/css\"/>\n</head>\n<body>\n<!-- Generated by Doxygen 1.7.1 -->\n<div class=\"navigation\" id=\"top\">\n  <div class=\"tabs\">\n    <ul class=\"tablist\">\n      <li><a href=\"index.html\"><span>Main&nbsp;Page</span></a></li>\n      <li><a href=\"modules.html\"><span>Modules</span></a></li>\n      <li class=\"current\"><a href=\"annotated.html\"><span>Data&nbsp;Structures</span></a></li>\n      <li><a href=\"files.html\"><span>Files</span></a></li>\n      <li><a href=\"examples.html\"><span>Examples</span></a></li>\n    </ul>\n  </div>\n  <div class=\"tabs2\">\n    <ul class=\"tablist\">\n      <li><a href=\"annotated.html\"><span>Data&nbsp;Structures</span></a></li>\n      <li><a href=\"functions.html\"><span>Data&nbsp;Fields</span></a></li>\n    </ul>\n  </div>\n</div>\n<div class=\"header\">\n  <div class=\"summary\">\n<a href=\"#pub-attribs\">Data Fields</a>  </div>\n  <div class=\"headertitle\">\n<h1>sp_session_callbacks Struct Reference<br/>\n<small>\n[<a class=\"el\" href=\"group__session.html\">Session handling</a>]</small>\n</h1>  </div>\n</div>\n<div class=\"contents\">\n<!-- doxytag: class=\"sp_session_callbacks\" -->\n<p><code>#include &lt;api.h&gt;</code></p>\n<table class=\"memberdecls\">\n<tr><td colspan=\"2\"><h2><a name=\"pub-attribs\"></a>\nData Fields</h2></td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">void(*&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"structsp__session__callbacks.html#a52d509962541f7d8fdd71284f40d8415\">logged_in</a> )(<a class=\"el\" href=\"group__types.html#ga70dd19c6f824cf6a159575aa4c128b53\">sp_session</a> *session, <a class=\"el\" href=\"group__error.html#gafd27986ce4cd9eeaeca8adda83c9eb6b\">sp_error</a> error)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">void(*&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"structsp__session__callbacks.html#a073231e9ceb3d40f4a772ab64ba4ece7\">logged_out</a> )(<a class=\"el\" href=\"group__types.html#ga70dd19c6f824cf6a159575aa4c128b53\">sp_session</a> *session)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">void(*&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"structsp__session__callbacks.html#a09912988f00ea5e90835681b382a18fc\">metadata_updated</a> )(<a class=\"el\" href=\"group__types.html#ga70dd19c6f824cf6a159575aa4c128b53\">sp_session</a> *session)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">void(*&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"structsp__session__callbacks.html#a45bf5d3fac7953099a191ea39fcfc018\">connection_error</a> )(<a class=\"el\" href=\"group__types.html#ga70dd19c6f824cf6a159575aa4c128b53\">sp_session</a> *session, <a class=\"el\" href=\"group__error.html#gafd27986ce4cd9eeaeca8adda83c9eb6b\">sp_error</a> error)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">void(*&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"structsp__session__callbacks.html#ae5d6e4a9a4296cfcbca1e57acdb4d64d\">message_to_user</a> )(<a class=\"el\" href=\"group__types.html#ga70dd19c6f824cf6a159575aa4c128b53\">sp_session</a> *session, const char *message)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">void(*&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"structsp__session__callbacks.html#a085cfd82e77aee2b592f314321019a29\">notify_main_thread</a> )(<a class=\"el\" href=\"group__types.html#ga70dd19c6f824cf6a159575aa4c128b53\">sp_session</a> *session)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">int(*&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"structsp__session__callbacks.html#a33a31478b8de1882ad7847ad033fbaeb\">music_delivery</a> )(<a class=\"el\" href=\"group__types.html#ga70dd19c6f824cf6a159575aa4c128b53\">sp_session</a> *session, const <a class=\"el\" href=\"structsp__audioformat.html\">sp_audioformat</a> *format, const void *frames, int num_frames)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">void(*&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"structsp__session__callbacks.html#a641fc97950305fbcd83d5114918c53b9\">play_token_lost</a> )(<a class=\"el\" href=\"group__types.html#ga70dd19c6f824cf6a159575aa4c128b53\">sp_session</a> *session)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">void(*&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"structsp__session__callbacks.html#aae0ce9c91f2779fafa40ebd640060a05\">log_message</a> )(<a class=\"el\" href=\"group__types.html#ga70dd19c6f824cf6a159575aa4c128b53\">sp_session</a> *session, const char *data)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">void(*&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"structsp__session__callbacks.html#a6bc198d89ff46d930c32dae950bd0294\">end_of_track</a> )(<a class=\"el\" href=\"group__types.html#ga70dd19c6f824cf6a159575aa4c128b53\">sp_session</a> *session)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">void(*&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"structsp__session__callbacks.html#a003db54ec10236a3e3d77bfbf31f38ae\">streaming_error</a> )(<a class=\"el\" href=\"group__types.html#ga70dd19c6f824cf6a159575aa4c128b53\">sp_session</a> *session, <a class=\"el\" href=\"group__error.html#gafd27986ce4cd9eeaeca8adda83c9eb6b\">sp_error</a> error)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">void(*&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"structsp__session__callbacks.html#a8685310c1755044ec0ea0e316de8be6e\">userinfo_updated</a> )(<a class=\"el\" href=\"group__types.html#ga70dd19c6f824cf6a159575aa4c128b53\">sp_session</a> *session)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">void(*&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"structsp__session__callbacks.html#adcfcee6abf1b6f408010e5615d2a79c8\">start_playback</a> )(<a class=\"el\" href=\"group__types.html#ga70dd19c6f824cf6a159575aa4c128b53\">sp_session</a> *session)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">void(*&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"structsp__session__callbacks.html#a2a225bc017266c935c05d18142f27ad6\">stop_playback</a> )(<a class=\"el\" href=\"group__types.html#ga70dd19c6f824cf6a159575aa4c128b53\">sp_session</a> *session)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">void(*&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"structsp__session__callbacks.html#a328404ac150210387ea3f9cc973149c9\">get_audio_buffer_stats</a> )(<a class=\"el\" href=\"group__types.html#ga70dd19c6f824cf6a159575aa4c128b53\">sp_session</a> *session, <a class=\"el\" href=\"structsp__audio__buffer__stats.html\">sp_audio_buffer_stats</a> *stats)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">void(*&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"structsp__session__callbacks.html#aa0f62ed875aab47e5ae093576a6d54c8\">offline_status_updated</a> )(<a class=\"el\" href=\"group__types.html#ga70dd19c6f824cf6a159575aa4c128b53\">sp_session</a> *session)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">void(*&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"structsp__session__callbacks.html#ad403ac063f5512b277c924add75dfbea\">offline_error</a> )(<a class=\"el\" href=\"group__types.html#ga70dd19c6f824cf6a159575aa4c128b53\">sp_session</a> *session, <a class=\"el\" href=\"group__error.html#gafd27986ce4cd9eeaeca8adda83c9eb6b\">sp_error</a> error)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">void(*&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"structsp__session__callbacks.html#ae7c5c209735f5c437d76a512eebbf30b\">credentials_blob_updated</a> )(<a class=\"el\" href=\"group__types.html#ga70dd19c6f824cf6a159575aa4c128b53\">sp_session</a> *session, const char *blob)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">void(*&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"structsp__session__callbacks.html#a379c96577e927d6c65ac61fe13c1e412\">connectionstate_updated</a> )(<a class=\"el\" href=\"group__types.html#ga70dd19c6f824cf6a159575aa4c128b53\">sp_session</a> *session)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">void(*&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"structsp__session__callbacks.html#a01a47778439fa233187fdefa75a0f7dc\">scrobble_error</a> )(<a class=\"el\" href=\"group__types.html#ga70dd19c6f824cf6a159575aa4c128b53\">sp_session</a> *session, <a class=\"el\" href=\"group__error.html#gafd27986ce4cd9eeaeca8adda83c9eb6b\">sp_error</a> error)</td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">void(*&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"structsp__session__callbacks.html#ad04af396785f8973a3c15a68bb617830\">private_session_mode_changed</a> )(<a class=\"el\" href=\"group__types.html#ga70dd19c6f824cf6a159575aa4c128b53\">sp_session</a> *session, bool is_private)</td></tr>\n</table>\n<hr/><a name=\"_details\"></a><h2>Detailed Description</h2>\n<p>Session callbacks</p>\n<p>Registered when you create a session. If some callbacks should not be of interest, set them to NULL. </p>\n<dl><dt><b>Examples: </b></dt><dd>\n<p><a class=\"el\" href=\"jukebox_8c-example.html#_a21\">jukebox.c</a>.</p>\n</dd>\n</dl><hr/><h2>Field Documentation</h2>\n<a class=\"anchor\" id=\"a45bf5d3fac7953099a191ea39fcfc018\"></a><!-- doxytag: member=\"sp_session_callbacks::connection_error\" ref=\"a45bf5d3fac7953099a191ea39fcfc018\" args=\")(sp_session *session, sp_error error)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\">void( * <a class=\"el\" href=\"structsp__session__callbacks.html#a45bf5d3fac7953099a191ea39fcfc018\">sp_session_callbacks::connection_error</a>)(<a class=\"el\" href=\"group__types.html#ga70dd19c6f824cf6a159575aa4c128b53\">sp_session</a> *session, <a class=\"el\" href=\"group__error.html#gafd27986ce4cd9eeaeca8adda83c9eb6b\">sp_error</a> error)</td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Called when there is a connection error, and the library has problems reconnecting to the Spotify service. Could be called multiple times (as long as the problem is present)</p>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>session</em>&nbsp;</td><td>Session </td></tr>\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>error</em>&nbsp;</td><td>One of the following errors, from <a class=\"el\" href=\"group__error.html#ga83154178d3a32668658734d2facfa22b\">sp_error</a> SP_ERROR_OK SP_ERROR_CLIENT_TOO_OLD SP_ERROR_UNABLE_TO_CONTACT_SERVER SP_ERROR_BAD_USERNAME_OR_PASSWORD SP_ERROR_USER_BANNED SP_ERROR_USER_NEEDS_PREMIUM SP_ERROR_OTHER_TRANSIENT SP_ERROR_OTHER_PERMANENT </td></tr>\n  </table>\n  </dd>\n</dl>\n\n</div>\n</div>\n<a class=\"anchor\" id=\"a379c96577e927d6c65ac61fe13c1e412\"></a><!-- doxytag: member=\"sp_session_callbacks::connectionstate_updated\" ref=\"a379c96577e927d6c65ac61fe13c1e412\" args=\")(sp_session *session)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\">void( * <a class=\"el\" href=\"structsp__session__callbacks.html#a379c96577e927d6c65ac61fe13c1e412\">sp_session_callbacks::connectionstate_updated</a>)(<a class=\"el\" href=\"group__types.html#ga70dd19c6f824cf6a159575aa4c128b53\">sp_session</a> *session)</td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Called when the connection state has updated - such as when logging in, going offline, etc.</p>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>session</em>&nbsp;</td><td>Session </td></tr>\n  </table>\n  </dd>\n</dl>\n\n</div>\n</div>\n<a class=\"anchor\" id=\"ae7c5c209735f5c437d76a512eebbf30b\"></a><!-- doxytag: member=\"sp_session_callbacks::credentials_blob_updated\" ref=\"ae7c5c209735f5c437d76a512eebbf30b\" args=\")(sp_session *session, const char *blob)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\">void( * <a class=\"el\" href=\"structsp__session__callbacks.html#ae7c5c209735f5c437d76a512eebbf30b\">sp_session_callbacks::credentials_blob_updated</a>)(<a class=\"el\" href=\"group__types.html#ga70dd19c6f824cf6a159575aa4c128b53\">sp_session</a> *session, const char *blob)</td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Called when storable credentials have been updated, usually called when we have connected to the AP.</p>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>session</em>&nbsp;</td><td>Session </td></tr>\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>blob</em>&nbsp;</td><td>Blob is a null-terminated string which contains an encrypted token that can be stored safely on disk instead of storing plaintext passwords. </td></tr>\n  </table>\n  </dd>\n</dl>\n\n</div>\n</div>\n<a class=\"anchor\" id=\"a6bc198d89ff46d930c32dae950bd0294\"></a><!-- doxytag: member=\"sp_session_callbacks::end_of_track\" ref=\"a6bc198d89ff46d930c32dae950bd0294\" args=\")(sp_session *session)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\">void( * <a class=\"el\" href=\"structsp__session__callbacks.html#a6bc198d89ff46d930c32dae950bd0294\">sp_session_callbacks::end_of_track</a>)(<a class=\"el\" href=\"group__types.html#ga70dd19c6f824cf6a159575aa4c128b53\">sp_session</a> *session)</td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>End of track. Called when the currently played track has reached its end.</p>\n<dl class=\"note\"><dt><b>Note:</b></dt><dd>This function is invoked from the main thread</dd></dl>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>session</em>&nbsp;</td><td>Session </td></tr>\n  </table>\n  </dd>\n</dl>\n\n</div>\n</div>\n<a class=\"anchor\" id=\"a328404ac150210387ea3f9cc973149c9\"></a><!-- doxytag: member=\"sp_session_callbacks::get_audio_buffer_stats\" ref=\"a328404ac150210387ea3f9cc973149c9\" args=\")(sp_session *session, sp_audio_buffer_stats *stats)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\">void( * <a class=\"el\" href=\"structsp__session__callbacks.html#a328404ac150210387ea3f9cc973149c9\">sp_session_callbacks::get_audio_buffer_stats</a>)(<a class=\"el\" href=\"group__types.html#ga70dd19c6f824cf6a159575aa4c128b53\">sp_session</a> *session, <a class=\"el\" href=\"structsp__audio__buffer__stats.html\">sp_audio_buffer_stats</a> *stats)</td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Called to query application about its audio buffer</p>\n<dl class=\"note\"><dt><b>Note:</b></dt><dd>This function is called from an internal session thread - you need to have proper synchronization!</dd>\n<dd>\nThis function must never block.</dd></dl>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>session</em>&nbsp;</td><td>Session </td></tr>\n    <tr><td valign=\"top\"><tt>[out]</tt>&nbsp;</td><td valign=\"top\"><em>stats</em>&nbsp;</td><td>Stats struct to be filled by application </td></tr>\n  </table>\n  </dd>\n</dl>\n\n</div>\n</div>\n<a class=\"anchor\" id=\"aae0ce9c91f2779fafa40ebd640060a05\"></a><!-- doxytag: member=\"sp_session_callbacks::log_message\" ref=\"aae0ce9c91f2779fafa40ebd640060a05\" args=\")(sp_session *session, const char *data)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\">void( * <a class=\"el\" href=\"structsp__session__callbacks.html#aae0ce9c91f2779fafa40ebd640060a05\">sp_session_callbacks::log_message</a>)(<a class=\"el\" href=\"group__types.html#ga70dd19c6f824cf6a159575aa4c128b53\">sp_session</a> *session, const char *data)</td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Logging callback.</p>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>session</em>&nbsp;</td><td>Session </td></tr>\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>data</em>&nbsp;</td><td>Log data </td></tr>\n  </table>\n  </dd>\n</dl>\n\n</div>\n</div>\n<a class=\"anchor\" id=\"a52d509962541f7d8fdd71284f40d8415\"></a><!-- doxytag: member=\"sp_session_callbacks::logged_in\" ref=\"a52d509962541f7d8fdd71284f40d8415\" args=\")(sp_session *session, sp_error error)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\">void( * <a class=\"el\" href=\"structsp__session__callbacks.html#a52d509962541f7d8fdd71284f40d8415\">sp_session_callbacks::logged_in</a>)(<a class=\"el\" href=\"group__types.html#ga70dd19c6f824cf6a159575aa4c128b53\">sp_session</a> *session, <a class=\"el\" href=\"group__error.html#gafd27986ce4cd9eeaeca8adda83c9eb6b\">sp_error</a> error)</td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Called when login has been processed and was successful</p>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>session</em>&nbsp;</td><td>Session </td></tr>\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>error</em>&nbsp;</td><td>One of the following errors, from <a class=\"el\" href=\"group__error.html#ga83154178d3a32668658734d2facfa22b\">sp_error</a> SP_ERROR_OK SP_ERROR_CLIENT_TOO_OLD SP_ERROR_UNABLE_TO_CONTACT_SERVER SP_ERROR_BAD_USERNAME_OR_PASSWORD SP_ERROR_USER_BANNED SP_ERROR_USER_NEEDS_PREMIUM SP_ERROR_OTHER_TRANSIENT SP_ERROR_OTHER_PERMANENT </td></tr>\n  </table>\n  </dd>\n</dl>\n\n</div>\n</div>\n<a class=\"anchor\" id=\"a073231e9ceb3d40f4a772ab64ba4ece7\"></a><!-- doxytag: member=\"sp_session_callbacks::logged_out\" ref=\"a073231e9ceb3d40f4a772ab64ba4ece7\" args=\")(sp_session *session)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\">void( * <a class=\"el\" href=\"structsp__session__callbacks.html#a073231e9ceb3d40f4a772ab64ba4ece7\">sp_session_callbacks::logged_out</a>)(<a class=\"el\" href=\"group__types.html#ga70dd19c6f824cf6a159575aa4c128b53\">sp_session</a> *session)</td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Called when logout has been processed. Either called explicitly if you initialize a logout operation, or implicitly if there is a permanent connection error</p>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>session</em>&nbsp;</td><td>Session </td></tr>\n  </table>\n  </dd>\n</dl>\n\n</div>\n</div>\n<a class=\"anchor\" id=\"ae5d6e4a9a4296cfcbca1e57acdb4d64d\"></a><!-- doxytag: member=\"sp_session_callbacks::message_to_user\" ref=\"ae5d6e4a9a4296cfcbca1e57acdb4d64d\" args=\")(sp_session *session, const char *message)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\">void( * <a class=\"el\" href=\"structsp__session__callbacks.html#ae5d6e4a9a4296cfcbca1e57acdb4d64d\">sp_session_callbacks::message_to_user</a>)(<a class=\"el\" href=\"group__types.html#ga70dd19c6f824cf6a159575aa4c128b53\">sp_session</a> *session, const char *message)</td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Called when the access point wants to display a message to the user</p>\n<p>In the desktop client, these are shown in a blueish toolbar just below the search box.</p>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>session</em>&nbsp;</td><td>Session </td></tr>\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>message</em>&nbsp;</td><td>String in UTF-8 format. </td></tr>\n  </table>\n  </dd>\n</dl>\n\n</div>\n</div>\n<a class=\"anchor\" id=\"a09912988f00ea5e90835681b382a18fc\"></a><!-- doxytag: member=\"sp_session_callbacks::metadata_updated\" ref=\"a09912988f00ea5e90835681b382a18fc\" args=\")(sp_session *session)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\">void( * <a class=\"el\" href=\"structsp__session__callbacks.html#a09912988f00ea5e90835681b382a18fc\">sp_session_callbacks::metadata_updated</a>)(<a class=\"el\" href=\"group__types.html#ga70dd19c6f824cf6a159575aa4c128b53\">sp_session</a> *session)</td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Called whenever metadata has been updated</p>\n<p>If you have metadata cached outside of libspotify, you should purge your caches and fetch new versions.</p>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>session</em>&nbsp;</td><td>Session </td></tr>\n  </table>\n  </dd>\n</dl>\n\n</div>\n</div>\n<a class=\"anchor\" id=\"a33a31478b8de1882ad7847ad033fbaeb\"></a><!-- doxytag: member=\"sp_session_callbacks::music_delivery\" ref=\"a33a31478b8de1882ad7847ad033fbaeb\" args=\")(sp_session *session, const sp_audioformat *format, const void *frames, int num_frames)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\">int( * <a class=\"el\" href=\"structsp__session__callbacks.html#a33a31478b8de1882ad7847ad033fbaeb\">sp_session_callbacks::music_delivery</a>)(<a class=\"el\" href=\"group__types.html#ga70dd19c6f824cf6a159575aa4c128b53\">sp_session</a> *session, const <a class=\"el\" href=\"structsp__audioformat.html\">sp_audioformat</a> *format, const void *frames, int num_frames)</td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Called when there is decompressed audio data available.</p>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>session</em>&nbsp;</td><td>Session </td></tr>\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>format</em>&nbsp;</td><td>Audio format descriptor <a class=\"el\" href=\"structsp__audioformat.html\">sp_audioformat</a> </td></tr>\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>frames</em>&nbsp;</td><td>Points to raw PCM data as described by <code>format</code> </td></tr>\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>num_frames</em>&nbsp;</td><td>Number of available samples in <code>frames</code>. If this is 0, a discontinuity has occurred (such as after a seek). The application should flush its audio fifos, etc.</td></tr>\n  </table>\n  </dd>\n</dl>\n<dl class=\"return\"><dt><b>Returns:</b></dt><dd>Number of frames consumed. This value can be used to rate limit the output from the library if your output buffers are saturated. The library will retry delivery in about 100ms.</dd></dl>\n<dl class=\"note\"><dt><b>Note:</b></dt><dd>This function is called from an internal session thread - you need to have proper synchronization!</dd>\n<dd>\nThis function must never block. If your output buffers are full you must return 0 to signal that the library should retry delivery in a short while. </dd></dl>\n\n</div>\n</div>\n<a class=\"anchor\" id=\"a085cfd82e77aee2b592f314321019a29\"></a><!-- doxytag: member=\"sp_session_callbacks::notify_main_thread\" ref=\"a085cfd82e77aee2b592f314321019a29\" args=\")(sp_session *session)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\">void( * <a class=\"el\" href=\"structsp__session__callbacks.html#a085cfd82e77aee2b592f314321019a29\">sp_session_callbacks::notify_main_thread</a>)(<a class=\"el\" href=\"group__types.html#ga70dd19c6f824cf6a159575aa4c128b53\">sp_session</a> *session)</td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Called when processing needs to take place on the main thread.</p>\n<p>You need to call <a class=\"el\" href=\"group__session.html#gaff27cb730db6debf55e750e39e7fadd7\">sp_session_process_events()</a> in the main thread to get libspotify to do more work. Failure to do so may cause request timeouts, or a lost connection.</p>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>session</em>&nbsp;</td><td>Session</td></tr>\n  </table>\n  </dd>\n</dl>\n<dl class=\"note\"><dt><b>Note:</b></dt><dd>This function is called from an internal session thread - you need to have proper synchronization! </dd></dl>\n\n</div>\n</div>\n<a class=\"anchor\" id=\"ad403ac063f5512b277c924add75dfbea\"></a><!-- doxytag: member=\"sp_session_callbacks::offline_error\" ref=\"ad403ac063f5512b277c924add75dfbea\" args=\")(sp_session *session, sp_error error)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\">void( * <a class=\"el\" href=\"structsp__session__callbacks.html#ad403ac063f5512b277c924add75dfbea\">sp_session_callbacks::offline_error</a>)(<a class=\"el\" href=\"group__types.html#ga70dd19c6f824cf6a159575aa4c128b53\">sp_session</a> *session, <a class=\"el\" href=\"group__error.html#gafd27986ce4cd9eeaeca8adda83c9eb6b\">sp_error</a> error)</td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Called when offline synchronization status is updated</p>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>session</em>&nbsp;</td><td>Session </td></tr>\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>error</em>&nbsp;</td><td>Offline error. Will be SP_ERROR_OK if the offline synchronization error state has cleared </td></tr>\n  </table>\n  </dd>\n</dl>\n\n</div>\n</div>\n<a class=\"anchor\" id=\"aa0f62ed875aab47e5ae093576a6d54c8\"></a><!-- doxytag: member=\"sp_session_callbacks::offline_status_updated\" ref=\"aa0f62ed875aab47e5ae093576a6d54c8\" args=\")(sp_session *session)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\">void( * <a class=\"el\" href=\"structsp__session__callbacks.html#aa0f62ed875aab47e5ae093576a6d54c8\">sp_session_callbacks::offline_status_updated</a>)(<a class=\"el\" href=\"group__types.html#ga70dd19c6f824cf6a159575aa4c128b53\">sp_session</a> *session)</td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Called when offline synchronization status is updated</p>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>session</em>&nbsp;</td><td>Session </td></tr>\n  </table>\n  </dd>\n</dl>\n\n</div>\n</div>\n<a class=\"anchor\" id=\"a641fc97950305fbcd83d5114918c53b9\"></a><!-- doxytag: member=\"sp_session_callbacks::play_token_lost\" ref=\"a641fc97950305fbcd83d5114918c53b9\" args=\")(sp_session *session)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\">void( * <a class=\"el\" href=\"structsp__session__callbacks.html#a641fc97950305fbcd83d5114918c53b9\">sp_session_callbacks::play_token_lost</a>)(<a class=\"el\" href=\"group__types.html#ga70dd19c6f824cf6a159575aa4c128b53\">sp_session</a> *session)</td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Music has been paused because an account only allows music to be played from one location simultaneously.</p>\n<dl class=\"note\"><dt><b>Note:</b></dt><dd>When this callback is invoked the application should behave just as if the user pressed the pause button. The application should also display a message to the user indicating the playback has been paused because another application is playing using the same account.</dd>\n<dd>\nIT MUST NOT automatically resume playback but must instead wait for the user to press play.</dd></dl>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>session</em>&nbsp;</td><td>Session </td></tr>\n  </table>\n  </dd>\n</dl>\n\n</div>\n</div>\n<a class=\"anchor\" id=\"ad04af396785f8973a3c15a68bb617830\"></a><!-- doxytag: member=\"sp_session_callbacks::private_session_mode_changed\" ref=\"ad04af396785f8973a3c15a68bb617830\" args=\")(sp_session *session, bool is_private)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\">void( * <a class=\"el\" href=\"structsp__session__callbacks.html#ad04af396785f8973a3c15a68bb617830\">sp_session_callbacks::private_session_mode_changed</a>)(<a class=\"el\" href=\"group__types.html#ga70dd19c6f824cf6a159575aa4c128b53\">sp_session</a> *session, bool is_private)</td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Called when there is a change in the private session mode</p>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>session</em>&nbsp;</td><td>Session </td></tr>\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>isPrivate</em>&nbsp;</td><td>True if in private session, false otherwhise </td></tr>\n  </table>\n  </dd>\n</dl>\n\n</div>\n</div>\n<a class=\"anchor\" id=\"a01a47778439fa233187fdefa75a0f7dc\"></a><!-- doxytag: member=\"sp_session_callbacks::scrobble_error\" ref=\"a01a47778439fa233187fdefa75a0f7dc\" args=\")(sp_session *session, sp_error error)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\">void( * <a class=\"el\" href=\"structsp__session__callbacks.html#a01a47778439fa233187fdefa75a0f7dc\">sp_session_callbacks::scrobble_error</a>)(<a class=\"el\" href=\"group__types.html#ga70dd19c6f824cf6a159575aa4c128b53\">sp_session</a> *session, <a class=\"el\" href=\"group__error.html#gafd27986ce4cd9eeaeca8adda83c9eb6b\">sp_error</a> error)</td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Called when there is a scrobble error event</p>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>session</em>&nbsp;</td><td>Session </td></tr>\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>error</em>&nbsp;</td><td>Scrobble error. Currently SP_ERROR_LASTFM_AUTH_ERROR. </td></tr>\n  </table>\n  </dd>\n</dl>\n\n</div>\n</div>\n<a class=\"anchor\" id=\"adcfcee6abf1b6f408010e5615d2a79c8\"></a><!-- doxytag: member=\"sp_session_callbacks::start_playback\" ref=\"adcfcee6abf1b6f408010e5615d2a79c8\" args=\")(sp_session *session)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\">void( * <a class=\"el\" href=\"structsp__session__callbacks.html#adcfcee6abf1b6f408010e5615d2a79c8\">sp_session_callbacks::start_playback</a>)(<a class=\"el\" href=\"group__types.html#ga70dd19c6f824cf6a159575aa4c128b53\">sp_session</a> *session)</td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Called when audio playback should start</p>\n<dl class=\"note\"><dt><b>Note:</b></dt><dd>For this to work correctly the application must also implement <a class=\"el\" href=\"structsp__session__callbacks.html#a328404ac150210387ea3f9cc973149c9\">get_audio_buffer_stats()</a></dd>\n<dd>\nThis function is called from an internal session thread - you need to have proper synchronization!</dd>\n<dd>\nThis function must never block.</dd></dl>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>session</em>&nbsp;</td><td>Session </td></tr>\n  </table>\n  </dd>\n</dl>\n\n</div>\n</div>\n<a class=\"anchor\" id=\"a2a225bc017266c935c05d18142f27ad6\"></a><!-- doxytag: member=\"sp_session_callbacks::stop_playback\" ref=\"a2a225bc017266c935c05d18142f27ad6\" args=\")(sp_session *session)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\">void( * <a class=\"el\" href=\"structsp__session__callbacks.html#a2a225bc017266c935c05d18142f27ad6\">sp_session_callbacks::stop_playback</a>)(<a class=\"el\" href=\"group__types.html#ga70dd19c6f824cf6a159575aa4c128b53\">sp_session</a> *session)</td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Called when audio playback should stop</p>\n<dl class=\"note\"><dt><b>Note:</b></dt><dd>For this to work correctly the application must also implement <a class=\"el\" href=\"structsp__session__callbacks.html#a328404ac150210387ea3f9cc973149c9\">get_audio_buffer_stats()</a></dd>\n<dd>\nThis function is called from an internal session thread - you need to have proper synchronization!</dd>\n<dd>\nThis function must never block.</dd></dl>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>session</em>&nbsp;</td><td>Session </td></tr>\n  </table>\n  </dd>\n</dl>\n\n</div>\n</div>\n<a class=\"anchor\" id=\"a003db54ec10236a3e3d77bfbf31f38ae\"></a><!-- doxytag: member=\"sp_session_callbacks::streaming_error\" ref=\"a003db54ec10236a3e3d77bfbf31f38ae\" args=\")(sp_session *session, sp_error error)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\">void( * <a class=\"el\" href=\"structsp__session__callbacks.html#a003db54ec10236a3e3d77bfbf31f38ae\">sp_session_callbacks::streaming_error</a>)(<a class=\"el\" href=\"group__types.html#ga70dd19c6f824cf6a159575aa4c128b53\">sp_session</a> *session, <a class=\"el\" href=\"group__error.html#gafd27986ce4cd9eeaeca8adda83c9eb6b\">sp_error</a> error)</td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Streaming error. Called when streaming cannot start or continue.</p>\n<dl class=\"note\"><dt><b>Note:</b></dt><dd>This function is invoked from the main thread</dd></dl>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>session</em>&nbsp;</td><td>Session </td></tr>\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>error</em>&nbsp;</td><td>One of the following errors, from <a class=\"el\" href=\"group__error.html#ga83154178d3a32668658734d2facfa22b\">sp_error</a> SP_ERROR_NO_STREAM_AVAILABLE SP_ERROR_OTHER_TRANSIENT SP_ERROR_OTHER_PERMANENT </td></tr>\n  </table>\n  </dd>\n</dl>\n\n</div>\n</div>\n<a class=\"anchor\" id=\"a8685310c1755044ec0ea0e316de8be6e\"></a><!-- doxytag: member=\"sp_session_callbacks::userinfo_updated\" ref=\"a8685310c1755044ec0ea0e316de8be6e\" args=\")(sp_session *session)\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\">void( * <a class=\"el\" href=\"structsp__session__callbacks.html#a8685310c1755044ec0ea0e316de8be6e\">sp_session_callbacks::userinfo_updated</a>)(<a class=\"el\" href=\"group__types.html#ga70dd19c6f824cf6a159575aa4c128b53\">sp_session</a> *session)</td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Called after user info (anything related to sp_user objects) have been updated.</p>\n<dl><dt><b>Parameters:</b></dt><dd>\n  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n    <tr><td valign=\"top\"><tt>[in]</tt>&nbsp;</td><td valign=\"top\"><em>session</em>&nbsp;</td><td>Session </td></tr>\n  </table>\n  </dd>\n</dl>\n\n</div>\n</div>\n<hr/>The documentation for this struct was generated from the following file:<ul>\n<li><a class=\"el\" href=\"api_8h.html\">api.h</a></li>\n</ul>\n</div>\n<hr size=\"1\"><address style=\"text-align: right;\"><small>\nGenerated on Wed Jun 13 2012 14:22:40.<br>\nCopyright &copy; 2006&ndash;2012 Spotify Ltd</small></address>\n</body>\n</html>\n"
  },
  {
    "path": "libspotify/docs/html/structsp__session__config.html",
    "content": "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\n<html xmlns=\"http://www.w3.org/1999/xhtml\">\n<head>\n<meta http-equiv=\"Content-Type\" content=\"text/xhtml;charset=UTF-8\"/>\n<title>libspotify: sp_session_config Struct Reference</title>\n<link href=\"tabs.css\" rel=\"stylesheet\" type=\"text/css\"/>\n<link href=\"doxygen.css\" rel=\"stylesheet\" type=\"text/css\"/>\n</head>\n<body>\n<!-- Generated by Doxygen 1.7.1 -->\n<div class=\"navigation\" id=\"top\">\n  <div class=\"tabs\">\n    <ul class=\"tablist\">\n      <li><a href=\"index.html\"><span>Main&nbsp;Page</span></a></li>\n      <li><a href=\"modules.html\"><span>Modules</span></a></li>\n      <li class=\"current\"><a href=\"annotated.html\"><span>Data&nbsp;Structures</span></a></li>\n      <li><a href=\"files.html\"><span>Files</span></a></li>\n      <li><a href=\"examples.html\"><span>Examples</span></a></li>\n    </ul>\n  </div>\n  <div class=\"tabs2\">\n    <ul class=\"tablist\">\n      <li><a href=\"annotated.html\"><span>Data&nbsp;Structures</span></a></li>\n      <li><a href=\"functions.html\"><span>Data&nbsp;Fields</span></a></li>\n    </ul>\n  </div>\n</div>\n<div class=\"header\">\n  <div class=\"summary\">\n<a href=\"#pub-attribs\">Data Fields</a>  </div>\n  <div class=\"headertitle\">\n<h1>sp_session_config Struct Reference<br/>\n<small>\n[<a class=\"el\" href=\"group__session.html\">Session handling</a>]</small>\n</h1>  </div>\n</div>\n<div class=\"contents\">\n<!-- doxytag: class=\"sp_session_config\" -->\n<p><code>#include &lt;api.h&gt;</code></p>\n<table class=\"memberdecls\">\n<tr><td colspan=\"2\"><h2><a name=\"pub-attribs\"></a>\nData Fields</h2></td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"anchor\" id=\"a1ed9d4ff26e6f666ba96dce41d5f1bac\"></a><!-- doxytag: member=\"sp_session_config::api_version\" ref=\"a1ed9d4ff26e6f666ba96dce41d5f1bac\" args=\"\" -->\nint&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"structsp__session__config.html#a1ed9d4ff26e6f666ba96dce41d5f1bac\">api_version</a></td></tr>\n<tr><td class=\"mdescLeft\">&nbsp;</td><td class=\"mdescRight\">The version of the Spotify API your application is compiled with. Set to <a class=\"el\" href=\"group__session.html#ga63b2309874193750ec3395f6cae32899\">SPOTIFY_API_VERSION</a>. <br/></td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">const char *&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"structsp__session__config.html#ad1cb5e3670451d8cee3d8c9766b523fc\">cache_location</a></td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">const char *&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"structsp__session__config.html#a342532432040d476aaaf73f10893d23b\">settings_location</a></td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"anchor\" id=\"ab5a5296a8e34bb454e7575940a19b9ae\"></a><!-- doxytag: member=\"sp_session_config::application_key\" ref=\"ab5a5296a8e34bb454e7575940a19b9ae\" args=\"\" -->\nconst void *&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"structsp__session__config.html#ab5a5296a8e34bb454e7575940a19b9ae\">application_key</a></td></tr>\n<tr><td class=\"mdescLeft\">&nbsp;</td><td class=\"mdescRight\">Your application key. <br/></td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"anchor\" id=\"ab10b332fe29b941162fd1d9ea1003b82\"></a><!-- doxytag: member=\"sp_session_config::application_key_size\" ref=\"ab10b332fe29b941162fd1d9ea1003b82\" args=\"\" -->\nsize_t&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"structsp__session__config.html#ab10b332fe29b941162fd1d9ea1003b82\">application_key_size</a></td></tr>\n<tr><td class=\"mdescLeft\">&nbsp;</td><td class=\"mdescRight\">The size of the application key in bytes. <br/></td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">const char *&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"structsp__session__config.html#a69d5b5aa58c901d7916bdea6e5b75c88\">user_agent</a></td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"anchor\" id=\"af0b456e6b9228ed812cd8ad28acbb127\"></a><!-- doxytag: member=\"sp_session_config::callbacks\" ref=\"af0b456e6b9228ed812cd8ad28acbb127\" args=\"\" -->\nconst <a class=\"el\" href=\"structsp__session__callbacks.html\">sp_session_callbacks</a> *&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"structsp__session__config.html#af0b456e6b9228ed812cd8ad28acbb127\">callbacks</a></td></tr>\n<tr><td class=\"mdescLeft\">&nbsp;</td><td class=\"mdescRight\">Delivery callbacks for session events, or NULL if you are not interested in any callbacks (not recommended!). <br/></td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"anchor\" id=\"a931b9a253380fdf910afc715e2c2d040\"></a><!-- doxytag: member=\"sp_session_config::userdata\" ref=\"a931b9a253380fdf910afc715e2c2d040\" args=\"\" -->\nvoid *&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"structsp__session__config.html#a931b9a253380fdf910afc715e2c2d040\">userdata</a></td></tr>\n<tr><td class=\"mdescLeft\">&nbsp;</td><td class=\"mdescRight\">User supplied data for your application. <br/></td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">bool&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"structsp__session__config.html#a8413a38bf3db9047b45525ac5dd4bc7b\">compress_playlists</a></td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">bool&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"structsp__session__config.html#a190139f3c0842cfe27c61ebf2da5ee9f\">dont_save_metadata_for_playlists</a></td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">bool&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"structsp__session__config.html#a3460b768cf69d1c646ac39f507e39287\">initially_unload_playlists</a></td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">const char *&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"structsp__session__config.html#af51c373555138dc4012501fa94b2bedc\">device_id</a></td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">const char *&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"structsp__session__config.html#af7a09f94350796ae7dde15a6518f51e2\">proxy</a></td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">const char *&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"structsp__session__config.html#a393cd7cf64c064f1647fe0045ac0d5cb\">proxy_username</a></td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">const char *&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"structsp__session__config.html#a33f2d3aa26d3db999b3026529aa5d670\">proxy_password</a></td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">const char *&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"structsp__session__config.html#a4a94ad4270e5401e68587952661bd3ca\">ca_certs_filename</a></td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\">const char *&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"structsp__session__config.html#aa7df4256deac84eea21053a7ca2cc3da\">tracefile</a></td></tr>\n</table>\n<hr/><a name=\"_details\"></a><h2>Detailed Description</h2>\n<p>Session config </p>\n<dl><dt><b>Examples: </b></dt><dd>\n<p><a class=\"el\" href=\"jukebox_8c-example.html#_a22\">jukebox.c</a>.</p>\n</dd>\n</dl><hr/><h2>Field Documentation</h2>\n<a class=\"anchor\" id=\"a4a94ad4270e5401e68587952661bd3ca\"></a><!-- doxytag: member=\"sp_session_config::ca_certs_filename\" ref=\"a4a94ad4270e5401e68587952661bd3ca\" args=\"\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\">const char* <a class=\"el\" href=\"structsp__session__config.html#a4a94ad4270e5401e68587952661bd3ca\">sp_session_config::ca_certs_filename</a></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Path to a file containing the root ca certificates that the peer should be verified with. The file must be a concatenation of all certificates in PEM format. Provided with libspotify is a sample pem file in examples. It is recommended that the application export a similar file from the local certificate store. </p>\n\n</div>\n</div>\n<a class=\"anchor\" id=\"ad1cb5e3670451d8cee3d8c9766b523fc\"></a><!-- doxytag: member=\"sp_session_config::cache_location\" ref=\"ad1cb5e3670451d8cee3d8c9766b523fc\" args=\"\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\">const char* <a class=\"el\" href=\"structsp__session__config.html#ad1cb5e3670451d8cee3d8c9766b523fc\">sp_session_config::cache_location</a></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>The location where Spotify will write cache files. This cache include tracks, cached browse results and coverarts. Set to empty string (\"\") to disable cache </p>\n\n</div>\n</div>\n<a class=\"anchor\" id=\"a8413a38bf3db9047b45525ac5dd4bc7b\"></a><!-- doxytag: member=\"sp_session_config::compress_playlists\" ref=\"a8413a38bf3db9047b45525ac5dd4bc7b\" args=\"\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\">bool <a class=\"el\" href=\"structsp__session__config.html#a8413a38bf3db9047b45525ac5dd4bc7b\">sp_session_config::compress_playlists</a></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Compress local copy of playlists, reduces disk space usage </p>\n\n</div>\n</div>\n<a class=\"anchor\" id=\"af51c373555138dc4012501fa94b2bedc\"></a><!-- doxytag: member=\"sp_session_config::device_id\" ref=\"af51c373555138dc4012501fa94b2bedc\" args=\"\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\">const char* <a class=\"el\" href=\"structsp__session__config.html#af51c373555138dc4012501fa94b2bedc\">sp_session_config::device_id</a></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Device ID for offline synchronization and logging purposes. The Device Id must be unique to the particular device instance, i.e. no two units must supply the same Device ID. The Device ID must not change between sessions or power cycles. Good examples is the device's MAC address or unique serial number. </p>\n\n</div>\n</div>\n<a class=\"anchor\" id=\"a190139f3c0842cfe27c61ebf2da5ee9f\"></a><!-- doxytag: member=\"sp_session_config::dont_save_metadata_for_playlists\" ref=\"a190139f3c0842cfe27c61ebf2da5ee9f\" args=\"\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\">bool <a class=\"el\" href=\"structsp__session__config.html#a190139f3c0842cfe27c61ebf2da5ee9f\">sp_session_config::dont_save_metadata_for_playlists</a></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Don't save metadata for local copies of playlists Reduces disk space usage at the expense of needing to request metadata from Spotify backend when loading list </p>\n\n</div>\n</div>\n<a class=\"anchor\" id=\"a3460b768cf69d1c646ac39f507e39287\"></a><!-- doxytag: member=\"sp_session_config::initially_unload_playlists\" ref=\"a3460b768cf69d1c646ac39f507e39287\" args=\"\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\">bool <a class=\"el\" href=\"structsp__session__config.html#a3460b768cf69d1c646ac39f507e39287\">sp_session_config::initially_unload_playlists</a></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Avoid loading playlists into RAM on startup. See <a class=\"el\" href=\"group__playlist.html#ga28456d1242693c6d890516dc782ab3ec\">sp_playlist_is_in_ram()</a> for more details. </p>\n\n</div>\n</div>\n<a class=\"anchor\" id=\"af7a09f94350796ae7dde15a6518f51e2\"></a><!-- doxytag: member=\"sp_session_config::proxy\" ref=\"af7a09f94350796ae7dde15a6518f51e2\" args=\"\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\">const char* <a class=\"el\" href=\"structsp__session__config.html#af7a09f94350796ae7dde15a6518f51e2\">sp_session_config::proxy</a></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Url to the proxy server that should be used. The format is protocol://&lt;host&gt;:port (where protocal is http/https/socks4/socks5) </p>\n\n</div>\n</div>\n<a class=\"anchor\" id=\"a33f2d3aa26d3db999b3026529aa5d670\"></a><!-- doxytag: member=\"sp_session_config::proxy_password\" ref=\"a33f2d3aa26d3db999b3026529aa5d670\" args=\"\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\">const char* <a class=\"el\" href=\"structsp__session__config.html#a33f2d3aa26d3db999b3026529aa5d670\">sp_session_config::proxy_password</a></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Password to authenticate with proxy server </p>\n\n</div>\n</div>\n<a class=\"anchor\" id=\"a393cd7cf64c064f1647fe0045ac0d5cb\"></a><!-- doxytag: member=\"sp_session_config::proxy_username\" ref=\"a393cd7cf64c064f1647fe0045ac0d5cb\" args=\"\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\">const char* <a class=\"el\" href=\"structsp__session__config.html#a393cd7cf64c064f1647fe0045ac0d5cb\">sp_session_config::proxy_username</a></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Username to authenticate with proxy server </p>\n\n</div>\n</div>\n<a class=\"anchor\" id=\"a342532432040d476aaaf73f10893d23b\"></a><!-- doxytag: member=\"sp_session_config::settings_location\" ref=\"a342532432040d476aaaf73f10893d23b\" args=\"\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\">const char* <a class=\"el\" href=\"structsp__session__config.html#a342532432040d476aaaf73f10893d23b\">sp_session_config::settings_location</a></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>The location where Spotify will write setting files and per-user cache items. This includes playlists, track metadata, etc. 'settings_location' may be the same path as 'cache_location'. 'settings_location' folder will not be created (unlike 'cache_location'), if you don't want to create the folder yourself, you can set 'settings_location' to 'cache_location'. </p>\n\n</div>\n</div>\n<a class=\"anchor\" id=\"aa7df4256deac84eea21053a7ca2cc3da\"></a><!-- doxytag: member=\"sp_session_config::tracefile\" ref=\"aa7df4256deac84eea21053a7ca2cc3da\" args=\"\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\">const char* <a class=\"el\" href=\"structsp__session__config.html#aa7df4256deac84eea21053a7ca2cc3da\">sp_session_config::tracefile</a></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>Path to API trace file </p>\n\n</div>\n</div>\n<a class=\"anchor\" id=\"a69d5b5aa58c901d7916bdea6e5b75c88\"></a><!-- doxytag: member=\"sp_session_config::user_agent\" ref=\"a69d5b5aa58c901d7916bdea6e5b75c88\" args=\"\" -->\n<div class=\"memitem\">\n<div class=\"memproto\">\n      <table class=\"memname\">\n        <tr>\n          <td class=\"memname\">const char* <a class=\"el\" href=\"structsp__session__config.html#a69d5b5aa58c901d7916bdea6e5b75c88\">sp_session_config::user_agent</a></td>\n        </tr>\n      </table>\n</div>\n<div class=\"memdoc\">\n<p>\"User-Agent\" for your application - max 255 characters long The User-Agent should be a relevant, customer facing identification of your application </p>\n\n</div>\n</div>\n<hr/>The documentation for this struct was generated from the following file:<ul>\n<li><a class=\"el\" href=\"api_8h.html\">api.h</a></li>\n</ul>\n</div>\n<hr size=\"1\"><address style=\"text-align: right;\"><small>\nGenerated on Wed Jun 13 2012 14:22:40.<br>\nCopyright &copy; 2006&ndash;2012 Spotify Ltd</small></address>\n</body>\n</html>\n"
  },
  {
    "path": "libspotify/docs/html/structsp__subscribers.html",
    "content": "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\n<html xmlns=\"http://www.w3.org/1999/xhtml\">\n<head>\n<meta http-equiv=\"Content-Type\" content=\"text/xhtml;charset=UTF-8\"/>\n<title>libspotify: sp_subscribers Struct Reference</title>\n<link href=\"tabs.css\" rel=\"stylesheet\" type=\"text/css\"/>\n<link href=\"doxygen.css\" rel=\"stylesheet\" type=\"text/css\"/>\n</head>\n<body>\n<!-- Generated by Doxygen 1.7.1 -->\n<div class=\"navigation\" id=\"top\">\n  <div class=\"tabs\">\n    <ul class=\"tablist\">\n      <li><a href=\"index.html\"><span>Main&nbsp;Page</span></a></li>\n      <li><a href=\"modules.html\"><span>Modules</span></a></li>\n      <li class=\"current\"><a href=\"annotated.html\"><span>Data&nbsp;Structures</span></a></li>\n      <li><a href=\"files.html\"><span>Files</span></a></li>\n      <li><a href=\"examples.html\"><span>Examples</span></a></li>\n    </ul>\n  </div>\n  <div class=\"tabs2\">\n    <ul class=\"tablist\">\n      <li><a href=\"annotated.html\"><span>Data&nbsp;Structures</span></a></li>\n      <li><a href=\"functions.html\"><span>Data&nbsp;Fields</span></a></li>\n    </ul>\n  </div>\n</div>\n<div class=\"header\">\n  <div class=\"summary\">\n<a href=\"#pub-attribs\">Data Fields</a>  </div>\n  <div class=\"headertitle\">\n<h1>sp_subscribers Struct Reference<br/>\n<small>\n[<a class=\"el\" href=\"group__session.html\">Session handling</a>]</small>\n</h1>  </div>\n</div>\n<div class=\"contents\">\n<!-- doxytag: class=\"sp_subscribers\" -->\n<p><code>#include &lt;api.h&gt;</code></p>\n<table class=\"memberdecls\">\n<tr><td colspan=\"2\"><h2><a name=\"pub-attribs\"></a>\nData Fields</h2></td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"anchor\" id=\"a37fd3d0daff9f2d856db1e891ce44bab\"></a><!-- doxytag: member=\"sp_subscribers::count\" ref=\"a37fd3d0daff9f2d856db1e891ce44bab\" args=\"\" -->\nunsigned int&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"structsp__subscribers.html#a37fd3d0daff9f2d856db1e891ce44bab\">count</a></td></tr>\n<tr><td class=\"mdescLeft\">&nbsp;</td><td class=\"mdescRight\">Number of elements in 'subscribers'. <br/></td></tr>\n<tr><td class=\"memItemLeft\" align=\"right\" valign=\"top\"><a class=\"anchor\" id=\"aaac89593785dc926976885dfd33efb0c\"></a><!-- doxytag: member=\"sp_subscribers::subscribers\" ref=\"aaac89593785dc926976885dfd33efb0c\" args=\"[1]\" -->\nchar *&nbsp;</td><td class=\"memItemRight\" valign=\"bottom\"><a class=\"el\" href=\"structsp__subscribers.html#aaac89593785dc926976885dfd33efb0c\">subscribers</a> [1]</td></tr>\n<tr><td class=\"mdescLeft\">&nbsp;</td><td class=\"mdescRight\">Actual size is 'count'. Array of pointers to canonical usernames. <br/></td></tr>\n</table>\n<hr/><a name=\"_details\"></a><h2>Detailed Description</h2>\n<p>List of subscribers returned by <a class=\"el\" href=\"group__playlist.html#gad49f491babc475f8d4aeea1b4452ff8b\">sp_playlist_subscribers()</a> </p>\n<hr/>The documentation for this struct was generated from the following file:<ul>\n<li><a class=\"el\" href=\"api_8h.html\">api.h</a></li>\n</ul>\n</div>\n<hr size=\"1\"><address style=\"text-align: right;\"><small>\nGenerated on Wed Jun 13 2012 14:22:40.<br>\nCopyright &copy; 2006&ndash;2012 Spotify Ltd</small></address>\n</body>\n</html>\n"
  },
  {
    "path": "libspotify/docs/html/tabs.css",
    "content": ".tabs, .tabs2, .tabs3 {\n    background-image: url('tab_b.png');\n    width: 100%;\n    z-index: 101;\n    font-size: 13px;\n}\n\n.tabs2 {\n    font-size: 10px;\n}\n.tabs3 {\n    font-size: 9px;\n}\n\n.tablist {\n    margin: 0;\n    padding: 0;\n    display: table;\n}\n\n.tablist li {\n    float: left;\n    display: table-cell;\n    background-image: url('tab_b.png');\n    line-height: 36px;\n    list-style: none;\n}\n\n.tablist a {\n    display: block;\n    padding: 0 20px;\n    font-weight: bold;\n    background-image:url('tab_s.png');\n    background-repeat:no-repeat;\n    background-position:right;\n    color: #283A5D;\n    text-shadow: 0px 1px 1px rgba(255, 255, 255, 0.9);\n    text-decoration: none;\n    outline: none;\n}\n\n.tabs3 .tablist a {\n    padding: 0 10px;\n}\n\n.tablist a:hover {\n    background-image: url('tab_h.png');\n    background-repeat:repeat-x;\n    color: #fff;\n    text-shadow: 0px 1px 1px rgba(0, 0, 0, 1.0);\n    text-decoration: none;\n}\n\n.tablist li.current a {\n    background-image: url('tab_a.png');\n    background-repeat:repeat-x;\n    color: #fff;\n    text-shadow: 0px 1px 1px rgba(0, 0, 0, 1.0);\n}\n"
  },
  {
    "path": "libspotify/docs/html/toplist_8c-example.html",
    "content": "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\n<html xmlns=\"http://www.w3.org/1999/xhtml\">\n<head>\n<meta http-equiv=\"Content-Type\" content=\"text/xhtml;charset=UTF-8\"/>\n<title>libspotify: toplist.c</title>\n<link href=\"tabs.css\" rel=\"stylesheet\" type=\"text/css\"/>\n<link href=\"doxygen.css\" rel=\"stylesheet\" type=\"text/css\"/>\n</head>\n<body>\n<!-- Generated by Doxygen 1.7.1 -->\n<div class=\"navigation\" id=\"top\">\n  <div class=\"tabs\">\n    <ul class=\"tablist\">\n      <li><a href=\"index.html\"><span>Main&nbsp;Page</span></a></li>\n      <li><a href=\"modules.html\"><span>Modules</span></a></li>\n      <li><a href=\"annotated.html\"><span>Data&nbsp;Structures</span></a></li>\n      <li><a href=\"files.html\"><span>Files</span></a></li>\n      <li><a href=\"examples.html\"><span>Examples</span></a></li>\n    </ul>\n  </div>\n</div>\n<div class=\"header\">\n  <div class=\"headertitle\">\n<h1>toplist.c</h1>  </div>\n</div>\n<div class=\"contents\">\n<p>The toplist.c example shows how you can use toplist functions. It is part of the spshell program</p>\n<div class=\"fragment\"><pre class=\"fragment\">\n<span class=\"preprocessor\">#include &lt;string.h&gt;</span>\n\n<span class=\"preprocessor\">#include &quot;spshell.h&quot;</span>\n<span class=\"preprocessor\">#include &quot;cmd.h&quot;</span>\n\n<span class=\"keyword\">static</span> <span class=\"keywordtype\">void</span> print_album(<span class=\"keywordtype\">int</span> index, <a class=\"code\" href=\"group__types.html#ga6fd3e5de729c429fef3ff18ece6dcfad\" title=\"An album handle.\">sp_album</a> *album)\n{\n    printf(<span class=\"stringliteral\">&quot;  Album %3d: \\&quot;%s\\&quot; by \\&quot;%s\\&quot;\\n&quot;</span>, index, <a name=\"a0\"></a><a class=\"code\" href=\"group__album.html#ga0e828c991a8184d60026513f944e19ad\">sp_album_name</a>(album), \n           <a name=\"a1\"></a><a class=\"code\" href=\"group__artist.html#gad2895555bb48514986823733a7afe5e2\">sp_artist_name</a>(<a name=\"a2\"></a><a class=\"code\" href=\"group__album.html#ga42309972141dab10c32d741d357c01de\">sp_album_artist</a>(album)));\n}\n\n<span class=\"keyword\">static</span> <span class=\"keywordtype\">void</span> print_artist(<span class=\"keywordtype\">int</span> index, <a class=\"code\" href=\"group__types.html#ga31764fbd69618c10be173c6c03d4c1bc\" title=\"An artist handle.\">sp_artist</a> *artist)\n{\n    <a class=\"code\" href=\"group__types.html#gaf90a23d6b662c96d52ac19f7f4bc1e39\" title=\"A handle to the libspotify internal representation of a URI.\">sp_link</a> *l;\n    <span class=\"keywordtype\">char</span> url[200];\n    printf(<span class=\"stringliteral\">&quot;  Artist %3d: \\&quot;%s\\&quot;\\n&quot;</span>, index, <a class=\"code\" href=\"group__artist.html#gad2895555bb48514986823733a7afe5e2\">sp_artist_name</a>(artist));\n\n    l = <a name=\"a3\"></a><a class=\"code\" href=\"group__link.html#gaafb25ee14bfb27f9cbbab1b039d4d225\">sp_link_create_from_artist_portrait</a>(artist, <a name=\"a4\"></a><a class=\"code\" href=\"group__session.html#gga61bc424465d776af3ceeb69eee2bb492ad20c808fd1f8180d1f49f643975d1dd7\" title=\"Normal image size.\">SP_IMAGE_SIZE_NORMAL</a>);\n    <span class=\"keywordflow\">if</span>(l != NULL) {\n        <a name=\"a5\"></a><a class=\"code\" href=\"group__link.html#ga9f169be53f098adcf12f7a10b8bd3ef7\">sp_link_as_string</a>(l, url, <span class=\"keyword\">sizeof</span>(url));\n        printf(<span class=\"stringliteral\">&quot;    Portrait: %s\\n&quot;</span>, url);\n        <a name=\"a6\"></a><a class=\"code\" href=\"group__link.html#ga2b06ab16d1f6436cd8d36dbff2b5c022\">sp_link_release</a>(l);\n    }\n}\n\n\n<span class=\"keyword\">static</span> <span class=\"keywordtype\">void</span> SP_CALLCONV got_toplist(<a class=\"code\" href=\"group__types.html#ga723de429cd073bcf5d13fb4e0f466ffd\" title=\"A handle to a toplist browse result.\">sp_toplistbrowse</a> *result, <span class=\"keywordtype\">void</span> *userdata)\n{\n    <span class=\"keywordtype\">int</span> i;\n\n    <span class=\"comment\">// We print from all types. Only one of the loops will acually yield anything.</span>\n\n    <span class=\"keywordflow\">for</span>(i = 0; i &lt; <a name=\"a7\"></a><a class=\"code\" href=\"group__toplist.html#gae2f5c09fbbf947834b1b1e73461f1fb3\">sp_toplistbrowse_num_artists</a>(result); i++)\n        print_artist(i + 1, <a name=\"a8\"></a><a class=\"code\" href=\"group__toplist.html#ga504cc45074d40c817dffbcc2906ef57f\">sp_toplistbrowse_artist</a>(result, i));\n\n    <span class=\"keywordflow\">for</span>(i = 0; i &lt; <a name=\"a9\"></a><a class=\"code\" href=\"group__toplist.html#ga69f5e70269c1eb08e1ddb1c77bb8c3e3\">sp_toplistbrowse_num_albums</a>(result); i++)\n        print_album(i + 1, <a name=\"a10\"></a><a class=\"code\" href=\"group__toplist.html#gaa080ace445d269f56942ac3d7f1f157e\">sp_toplistbrowse_album</a>(result, i));\n\n    <span class=\"keywordflow\">for</span>(i = 0; i &lt; <a name=\"a11\"></a><a class=\"code\" href=\"group__toplist.html#gaeb0ddfd565474dc7e444aabebbc119b7\">sp_toplistbrowse_num_tracks</a>(result); i++) {\n        printf(<span class=\"stringliteral\">&quot;%3d: &quot;</span>, i + 1);\n        print_track(<a name=\"a12\"></a><a class=\"code\" href=\"group__toplist.html#gaf3d00b8bf089134a4f320a8d3d6ab683\">sp_toplistbrowse_track</a>(result, i));\n    }\n\n    <a name=\"a13\"></a><a class=\"code\" href=\"group__toplist.html#gac6cf969c9cb6b431aeaa4723820ca8de\">sp_toplistbrowse_release</a>(result);\n    cmd_done();\n}\n\n\n\n<span class=\"keyword\">static</span> <span class=\"keywordtype\">void</span> toplist_usage(<span class=\"keywordtype\">void</span>)\n{\n    fprintf(stderr, <span class=\"stringliteral\">&quot;Usage: toplist (tracks | albums | artists) (global | region &lt;countrycode&gt; | user)\\n&quot;</span>);\n}\n\n<span class=\"keywordtype\">int</span> cmd_toplist(<span class=\"keywordtype\">int</span> argc, <span class=\"keywordtype\">char</span> **argv)\n{\n    <a class=\"code\" href=\"group__toplist.html#ga220f32522efb2828e4f8ffb949af234a\">sp_toplisttype</a> type;\n    <a class=\"code\" href=\"group__toplist.html#ga6fa5cfed2cbb33f2f64542d0b63f6c8d\">sp_toplistregion</a> region;\n\n    <span class=\"keywordflow\">if</span>(argc &lt; 3) {\n        toplist_usage();\n        <span class=\"keywordflow\">return</span> -1;\n    }\n\n    <span class=\"keywordflow\">if</span>(!strcasecmp(argv[1], <span class=\"stringliteral\">&quot;artists&quot;</span>))\n        type = SP_TOPLIST_TYPE_ARTISTS;\n    <span class=\"keywordflow\">else</span> <span class=\"keywordflow\">if</span>(!strcasecmp(argv[1], <span class=\"stringliteral\">&quot;albums&quot;</span>))\n        type = SP_TOPLIST_TYPE_ALBUMS;\n    <span class=\"keywordflow\">else</span> <span class=\"keywordflow\">if</span>(!strcasecmp(argv[1], <span class=\"stringliteral\">&quot;tracks&quot;</span>))\n        type = SP_TOPLIST_TYPE_TRACKS;\n    <span class=\"keywordflow\">else</span> {\n        toplist_usage();\n        <span class=\"keywordflow\">return</span> -1;\n    }\n\n\n    <span class=\"keywordflow\">if</span>(!strcasecmp(argv[2], <span class=\"stringliteral\">&quot;global&quot;</span>))\n        region = SP_TOPLIST_REGION_EVERYWHERE;\n    <span class=\"keywordflow\">else</span> <span class=\"keywordflow\">if</span>(!strcasecmp(argv[2], <span class=\"stringliteral\">&quot;user&quot;</span>))\n        region = SP_TOPLIST_REGION_USER;\n    <span class=\"keywordflow\">else</span> <span class=\"keywordflow\">if</span>(!strcasecmp(argv[2], <span class=\"stringliteral\">&quot;region&quot;</span>)) {\n\n        <span class=\"keywordflow\">if</span>(argc != 4 || strlen(argv[3]) != 2) {\n            toplist_usage();\n            <span class=\"keywordflow\">return</span> -1;\n        }\n        region = <a name=\"a14\"></a><a class=\"code\" href=\"group__toplist.html#gaa078b44491f976af43e4941fd1dd032c\">SP_TOPLIST_REGION</a>(argv[3][0], argv[3][1]);\n    } <span class=\"keywordflow\">else</span> {\n        toplist_usage();\n        <span class=\"keywordflow\">return</span> -1;\n    }\n\n    <a name=\"a15\"></a><a class=\"code\" href=\"group__toplist.html#gac2fe366e0050747438e09cdd22ed0e31\">sp_toplistbrowse_create</a>(g_session, type, region, NULL, got_toplist, NULL);\n    <span class=\"keywordflow\">return</span> 0;\n}\n</pre></div> </div>\n</div>\n<hr size=\"1\"><address style=\"text-align: right;\"><small>\nGenerated on Wed Jun 13 2012 14:22:40.<br>\nCopyright &copy; 2006&ndash;2012 Spotify Ltd</small></address>\n</body>\n</html>\n"
  },
  {
    "path": "libspotify/docs/images/spotify-core.txt",
    "content": "Uses SPOTIFY(R) CORE\n"
  },
  {
    "path": "libspotify/examples/Makefile",
    "content": "EXAMPLES=jukebox spshell localfiles\n\n.PHONY: all clean\n\nifdef LIBSPOTIFY_PATH\nARG=LIBSPOTIFY_PATH=\"$(shell cd \"$(LIBSPOTIFY_PATH)\" && pwd)\"\nendif\n\nall clean:\n\tfor a in $(EXAMPLES); do $(MAKE) -C $$a $(ARG) $@; done\n"
  },
  {
    "path": "libspotify/examples/Randomify/English.lproj/InfoPlist.strings",
    "content": "/* Localized versions of Info.plist keys */\n\n"
  },
  {
    "path": "libspotify/examples/Randomify/English.lproj/MainMenu.xib",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<archive type=\"com.apple.InterfaceBuilder3.Cocoa.XIB\" version=\"7.10\">\n\t<data>\n\t\t<int key=\"IBDocument.SystemTarget\">1050</int>\n\t\t<string key=\"IBDocument.SystemVersion\">10C540</string>\n\t\t<string key=\"IBDocument.InterfaceBuilderVersion\">740</string>\n\t\t<string key=\"IBDocument.AppKitVersion\">1038.25</string>\n\t\t<string key=\"IBDocument.HIToolboxVersion\">458.00</string>\n\t\t<object class=\"NSMutableDictionary\" key=\"IBDocument.PluginVersions\">\n\t\t\t<string key=\"NS.key.0\">com.apple.InterfaceBuilder.CocoaPlugin</string>\n\t\t\t<string key=\"NS.object.0\">740</string>\n\t\t</object>\n\t\t<object class=\"NSMutableArray\" key=\"IBDocument.EditedObjectIDs\">\n\t\t\t<bool key=\"EncodedWithXMLCoder\">YES</bool>\n\t\t\t<integer value=\"29\"/>\n\t\t\t<integer value=\"372\"/>\n\t\t</object>\n\t\t<object class=\"NSArray\" key=\"IBDocument.PluginDependencies\">\n\t\t\t<bool key=\"EncodedWithXMLCoder\">YES</bool>\n\t\t\t<string>com.apple.InterfaceBuilder.CocoaPlugin</string>\n\t\t</object>\n\t\t<object class=\"NSMutableDictionary\" key=\"IBDocument.Metadata\">\n\t\t\t<bool key=\"EncodedWithXMLCoder\">YES</bool>\n\t\t\t<object class=\"NSArray\" key=\"dict.sortedKeys\" id=\"0\">\n\t\t\t\t<bool key=\"EncodedWithXMLCoder\">YES</bool>\n\t\t\t</object>\n\t\t\t<object class=\"NSMutableArray\" key=\"dict.values\">\n\t\t\t\t<bool key=\"EncodedWithXMLCoder\">YES</bool>\n\t\t\t</object>\n\t\t</object>\n\t\t<object class=\"NSMutableArray\" key=\"IBDocument.RootObjects\" id=\"1048\">\n\t\t\t<bool key=\"EncodedWithXMLCoder\">YES</bool>\n\t\t\t<object class=\"NSCustomObject\" id=\"1021\">\n\t\t\t\t<string key=\"NSClassName\">NSApplication</string>\n\t\t\t</object>\n\t\t\t<object class=\"NSCustomObject\" id=\"1014\">\n\t\t\t\t<string key=\"NSClassName\">FirstResponder</string>\n\t\t\t</object>\n\t\t\t<object class=\"NSCustomObject\" id=\"1050\">\n\t\t\t\t<string key=\"NSClassName\">NSApplication</string>\n\t\t\t</object>\n\t\t\t<object class=\"NSMenu\" id=\"649796088\">\n\t\t\t\t<string key=\"NSTitle\">AMainMenu</string>\n\t\t\t\t<object class=\"NSMutableArray\" key=\"NSMenuItems\">\n\t\t\t\t\t<bool key=\"EncodedWithXMLCoder\">YES</bool>\n\t\t\t\t\t<object class=\"NSMenuItem\" id=\"694149608\">\n\t\t\t\t\t\t<reference key=\"NSMenu\" ref=\"649796088\"/>\n\t\t\t\t\t\t<string key=\"NSTitle\">Randomify</string>\n\t\t\t\t\t\t<string key=\"NSKeyEquiv\"/>\n\t\t\t\t\t\t<int key=\"NSKeyEquivModMask\">1048576</int>\n\t\t\t\t\t\t<int key=\"NSMnemonicLoc\">2147483647</int>\n\t\t\t\t\t\t<object class=\"NSCustomResource\" key=\"NSOnImage\" id=\"35465992\">\n\t\t\t\t\t\t\t<string key=\"NSClassName\">NSImage</string>\n\t\t\t\t\t\t\t<string key=\"NSResourceName\">NSMenuCheckmark</string>\n\t\t\t\t\t\t</object>\n\t\t\t\t\t\t<object class=\"NSCustomResource\" key=\"NSMixedImage\" id=\"502551668\">\n\t\t\t\t\t\t\t<string key=\"NSClassName\">NSImage</string>\n\t\t\t\t\t\t\t<string key=\"NSResourceName\">NSMenuMixedState</string>\n\t\t\t\t\t\t</object>\n\t\t\t\t\t\t<string key=\"NSAction\">submenuAction:</string>\n\t\t\t\t\t\t<object class=\"NSMenu\" key=\"NSSubmenu\" id=\"110575045\">\n\t\t\t\t\t\t\t<string key=\"NSTitle\">Randomify</string>\n\t\t\t\t\t\t\t<object class=\"NSMutableArray\" key=\"NSMenuItems\">\n\t\t\t\t\t\t\t\t<bool key=\"EncodedWithXMLCoder\">YES</bool>\n\t\t\t\t\t\t\t\t<object class=\"NSMenuItem\" id=\"238522557\">\n\t\t\t\t\t\t\t\t\t<reference key=\"NSMenu\" ref=\"110575045\"/>\n\t\t\t\t\t\t\t\t\t<string key=\"NSTitle\">About Randomify</string>\n\t\t\t\t\t\t\t\t\t<string key=\"NSKeyEquiv\"/>\n\t\t\t\t\t\t\t\t\t<int key=\"NSMnemonicLoc\">2147483647</int>\n\t\t\t\t\t\t\t\t\t<reference key=\"NSOnImage\" ref=\"35465992\"/>\n\t\t\t\t\t\t\t\t\t<reference key=\"NSMixedImage\" ref=\"502551668\"/>\n\t\t\t\t\t\t\t\t</object>\n\t\t\t\t\t\t\t\t<object class=\"NSMenuItem\" id=\"304266470\">\n\t\t\t\t\t\t\t\t\t<reference key=\"NSMenu\" ref=\"110575045\"/>\n\t\t\t\t\t\t\t\t\t<bool key=\"NSIsDisabled\">YES</bool>\n\t\t\t\t\t\t\t\t\t<bool key=\"NSIsSeparator\">YES</bool>\n\t\t\t\t\t\t\t\t\t<string key=\"NSTitle\"/>\n\t\t\t\t\t\t\t\t\t<string key=\"NSKeyEquiv\"/>\n\t\t\t\t\t\t\t\t\t<int key=\"NSKeyEquivModMask\">1048576</int>\n\t\t\t\t\t\t\t\t\t<int key=\"NSMnemonicLoc\">2147483647</int>\n\t\t\t\t\t\t\t\t\t<reference key=\"NSOnImage\" ref=\"35465992\"/>\n\t\t\t\t\t\t\t\t\t<reference key=\"NSMixedImage\" ref=\"502551668\"/>\n\t\t\t\t\t\t\t\t</object>\n\t\t\t\t\t\t\t\t<object class=\"NSMenuItem\" id=\"609285721\">\n\t\t\t\t\t\t\t\t\t<reference key=\"NSMenu\" ref=\"110575045\"/>\n\t\t\t\t\t\t\t\t\t<string key=\"NSTitle\">Preferences…</string>\n\t\t\t\t\t\t\t\t\t<string key=\"NSKeyEquiv\">,</string>\n\t\t\t\t\t\t\t\t\t<int key=\"NSKeyEquivModMask\">1048576</int>\n\t\t\t\t\t\t\t\t\t<int key=\"NSMnemonicLoc\">2147483647</int>\n\t\t\t\t\t\t\t\t\t<reference key=\"NSOnImage\" ref=\"35465992\"/>\n\t\t\t\t\t\t\t\t\t<reference key=\"NSMixedImage\" ref=\"502551668\"/>\n\t\t\t\t\t\t\t\t</object>\n\t\t\t\t\t\t\t\t<object class=\"NSMenuItem\" id=\"481834944\">\n\t\t\t\t\t\t\t\t\t<reference key=\"NSMenu\" ref=\"110575045\"/>\n\t\t\t\t\t\t\t\t\t<bool key=\"NSIsDisabled\">YES</bool>\n\t\t\t\t\t\t\t\t\t<bool key=\"NSIsSeparator\">YES</bool>\n\t\t\t\t\t\t\t\t\t<string key=\"NSTitle\"/>\n\t\t\t\t\t\t\t\t\t<string key=\"NSKeyEquiv\"/>\n\t\t\t\t\t\t\t\t\t<int key=\"NSKeyEquivModMask\">1048576</int>\n\t\t\t\t\t\t\t\t\t<int key=\"NSMnemonicLoc\">2147483647</int>\n\t\t\t\t\t\t\t\t\t<reference key=\"NSOnImage\" ref=\"35465992\"/>\n\t\t\t\t\t\t\t\t\t<reference key=\"NSMixedImage\" ref=\"502551668\"/>\n\t\t\t\t\t\t\t\t</object>\n\t\t\t\t\t\t\t\t<object class=\"NSMenuItem\" id=\"1046388886\">\n\t\t\t\t\t\t\t\t\t<reference key=\"NSMenu\" ref=\"110575045\"/>\n\t\t\t\t\t\t\t\t\t<string key=\"NSTitle\">Services</string>\n\t\t\t\t\t\t\t\t\t<string key=\"NSKeyEquiv\"/>\n\t\t\t\t\t\t\t\t\t<int key=\"NSKeyEquivModMask\">1048576</int>\n\t\t\t\t\t\t\t\t\t<int key=\"NSMnemonicLoc\">2147483647</int>\n\t\t\t\t\t\t\t\t\t<reference key=\"NSOnImage\" ref=\"35465992\"/>\n\t\t\t\t\t\t\t\t\t<reference key=\"NSMixedImage\" ref=\"502551668\"/>\n\t\t\t\t\t\t\t\t\t<string key=\"NSAction\">submenuAction:</string>\n\t\t\t\t\t\t\t\t\t<object class=\"NSMenu\" key=\"NSSubmenu\" id=\"752062318\">\n\t\t\t\t\t\t\t\t\t\t<string key=\"NSTitle\">Services</string>\n\t\t\t\t\t\t\t\t\t\t<object class=\"NSMutableArray\" key=\"NSMenuItems\">\n\t\t\t\t\t\t\t\t\t\t\t<bool key=\"EncodedWithXMLCoder\">YES</bool>\n\t\t\t\t\t\t\t\t\t\t</object>\n\t\t\t\t\t\t\t\t\t\t<string key=\"NSName\">_NSServicesMenu</string>\n\t\t\t\t\t\t\t\t\t</object>\n\t\t\t\t\t\t\t\t</object>\n\t\t\t\t\t\t\t\t<object class=\"NSMenuItem\" id=\"646227648\">\n\t\t\t\t\t\t\t\t\t<reference key=\"NSMenu\" ref=\"110575045\"/>\n\t\t\t\t\t\t\t\t\t<bool key=\"NSIsDisabled\">YES</bool>\n\t\t\t\t\t\t\t\t\t<bool key=\"NSIsSeparator\">YES</bool>\n\t\t\t\t\t\t\t\t\t<string key=\"NSTitle\"/>\n\t\t\t\t\t\t\t\t\t<string key=\"NSKeyEquiv\"/>\n\t\t\t\t\t\t\t\t\t<int key=\"NSKeyEquivModMask\">1048576</int>\n\t\t\t\t\t\t\t\t\t<int key=\"NSMnemonicLoc\">2147483647</int>\n\t\t\t\t\t\t\t\t\t<reference key=\"NSOnImage\" ref=\"35465992\"/>\n\t\t\t\t\t\t\t\t\t<reference key=\"NSMixedImage\" ref=\"502551668\"/>\n\t\t\t\t\t\t\t\t</object>\n\t\t\t\t\t\t\t\t<object class=\"NSMenuItem\" id=\"755159360\">\n\t\t\t\t\t\t\t\t\t<reference key=\"NSMenu\" ref=\"110575045\"/>\n\t\t\t\t\t\t\t\t\t<string key=\"NSTitle\">Hide Randomify</string>\n\t\t\t\t\t\t\t\t\t<string key=\"NSKeyEquiv\">h</string>\n\t\t\t\t\t\t\t\t\t<int key=\"NSKeyEquivModMask\">1048576</int>\n\t\t\t\t\t\t\t\t\t<int key=\"NSMnemonicLoc\">2147483647</int>\n\t\t\t\t\t\t\t\t\t<reference key=\"NSOnImage\" ref=\"35465992\"/>\n\t\t\t\t\t\t\t\t\t<reference key=\"NSMixedImage\" ref=\"502551668\"/>\n\t\t\t\t\t\t\t\t</object>\n\t\t\t\t\t\t\t\t<object class=\"NSMenuItem\" id=\"342932134\">\n\t\t\t\t\t\t\t\t\t<reference key=\"NSMenu\" ref=\"110575045\"/>\n\t\t\t\t\t\t\t\t\t<string key=\"NSTitle\">Hide Others</string>\n\t\t\t\t\t\t\t\t\t<string key=\"NSKeyEquiv\">h</string>\n\t\t\t\t\t\t\t\t\t<int key=\"NSKeyEquivModMask\">1572864</int>\n\t\t\t\t\t\t\t\t\t<int key=\"NSMnemonicLoc\">2147483647</int>\n\t\t\t\t\t\t\t\t\t<reference key=\"NSOnImage\" ref=\"35465992\"/>\n\t\t\t\t\t\t\t\t\t<reference key=\"NSMixedImage\" ref=\"502551668\"/>\n\t\t\t\t\t\t\t\t</object>\n\t\t\t\t\t\t\t\t<object class=\"NSMenuItem\" id=\"908899353\">\n\t\t\t\t\t\t\t\t\t<reference key=\"NSMenu\" ref=\"110575045\"/>\n\t\t\t\t\t\t\t\t\t<string key=\"NSTitle\">Show All</string>\n\t\t\t\t\t\t\t\t\t<string key=\"NSKeyEquiv\"/>\n\t\t\t\t\t\t\t\t\t<int key=\"NSKeyEquivModMask\">1048576</int>\n\t\t\t\t\t\t\t\t\t<int key=\"NSMnemonicLoc\">2147483647</int>\n\t\t\t\t\t\t\t\t\t<reference key=\"NSOnImage\" ref=\"35465992\"/>\n\t\t\t\t\t\t\t\t\t<reference key=\"NSMixedImage\" ref=\"502551668\"/>\n\t\t\t\t\t\t\t\t</object>\n\t\t\t\t\t\t\t\t<object class=\"NSMenuItem\" id=\"1056857174\">\n\t\t\t\t\t\t\t\t\t<reference key=\"NSMenu\" ref=\"110575045\"/>\n\t\t\t\t\t\t\t\t\t<bool key=\"NSIsDisabled\">YES</bool>\n\t\t\t\t\t\t\t\t\t<bool key=\"NSIsSeparator\">YES</bool>\n\t\t\t\t\t\t\t\t\t<string key=\"NSTitle\"/>\n\t\t\t\t\t\t\t\t\t<string key=\"NSKeyEquiv\"/>\n\t\t\t\t\t\t\t\t\t<int key=\"NSKeyEquivModMask\">1048576</int>\n\t\t\t\t\t\t\t\t\t<int key=\"NSMnemonicLoc\">2147483647</int>\n\t\t\t\t\t\t\t\t\t<reference key=\"NSOnImage\" ref=\"35465992\"/>\n\t\t\t\t\t\t\t\t\t<reference key=\"NSMixedImage\" ref=\"502551668\"/>\n\t\t\t\t\t\t\t\t</object>\n\t\t\t\t\t\t\t\t<object class=\"NSMenuItem\" id=\"632727374\">\n\t\t\t\t\t\t\t\t\t<reference key=\"NSMenu\" ref=\"110575045\"/>\n\t\t\t\t\t\t\t\t\t<string key=\"NSTitle\">Quit Randomify</string>\n\t\t\t\t\t\t\t\t\t<string key=\"NSKeyEquiv\">q</string>\n\t\t\t\t\t\t\t\t\t<int key=\"NSKeyEquivModMask\">1048576</int>\n\t\t\t\t\t\t\t\t\t<int key=\"NSMnemonicLoc\">2147483647</int>\n\t\t\t\t\t\t\t\t\t<reference key=\"NSOnImage\" ref=\"35465992\"/>\n\t\t\t\t\t\t\t\t\t<reference key=\"NSMixedImage\" ref=\"502551668\"/>\n\t\t\t\t\t\t\t\t</object>\n\t\t\t\t\t\t\t</object>\n\t\t\t\t\t\t\t<string key=\"NSName\">_NSAppleMenu</string>\n\t\t\t\t\t\t</object>\n\t\t\t\t\t</object>\n\t\t\t\t\t<object class=\"NSMenuItem\" id=\"379814623\">\n\t\t\t\t\t\t<reference key=\"NSMenu\" ref=\"649796088\"/>\n\t\t\t\t\t\t<string key=\"NSTitle\">File</string>\n\t\t\t\t\t\t<string key=\"NSKeyEquiv\"/>\n\t\t\t\t\t\t<int key=\"NSKeyEquivModMask\">1048576</int>\n\t\t\t\t\t\t<int key=\"NSMnemonicLoc\">2147483647</int>\n\t\t\t\t\t\t<reference key=\"NSOnImage\" ref=\"35465992\"/>\n\t\t\t\t\t\t<reference key=\"NSMixedImage\" ref=\"502551668\"/>\n\t\t\t\t\t\t<string key=\"NSAction\">submenuAction:</string>\n\t\t\t\t\t\t<object class=\"NSMenu\" key=\"NSSubmenu\" id=\"720053764\">\n\t\t\t\t\t\t\t<string key=\"NSTitle\">File</string>\n\t\t\t\t\t\t\t<object class=\"NSMutableArray\" key=\"NSMenuItems\">\n\t\t\t\t\t\t\t\t<bool key=\"EncodedWithXMLCoder\">YES</bool>\n\t\t\t\t\t\t\t\t<object class=\"NSMenuItem\" id=\"705341025\">\n\t\t\t\t\t\t\t\t\t<reference key=\"NSMenu\" ref=\"720053764\"/>\n\t\t\t\t\t\t\t\t\t<string key=\"NSTitle\">New</string>\n\t\t\t\t\t\t\t\t\t<string key=\"NSKeyEquiv\">n</string>\n\t\t\t\t\t\t\t\t\t<int key=\"NSKeyEquivModMask\">1048576</int>\n\t\t\t\t\t\t\t\t\t<int key=\"NSMnemonicLoc\">2147483647</int>\n\t\t\t\t\t\t\t\t\t<reference key=\"NSOnImage\" ref=\"35465992\"/>\n\t\t\t\t\t\t\t\t\t<reference key=\"NSMixedImage\" ref=\"502551668\"/>\n\t\t\t\t\t\t\t\t</object>\n\t\t\t\t\t\t\t\t<object class=\"NSMenuItem\" id=\"722745758\">\n\t\t\t\t\t\t\t\t\t<reference key=\"NSMenu\" ref=\"720053764\"/>\n\t\t\t\t\t\t\t\t\t<string key=\"NSTitle\">Open…</string>\n\t\t\t\t\t\t\t\t\t<string key=\"NSKeyEquiv\">o</string>\n\t\t\t\t\t\t\t\t\t<int key=\"NSKeyEquivModMask\">1048576</int>\n\t\t\t\t\t\t\t\t\t<int key=\"NSMnemonicLoc\">2147483647</int>\n\t\t\t\t\t\t\t\t\t<reference key=\"NSOnImage\" ref=\"35465992\"/>\n\t\t\t\t\t\t\t\t\t<reference key=\"NSMixedImage\" ref=\"502551668\"/>\n\t\t\t\t\t\t\t\t</object>\n\t\t\t\t\t\t\t\t<object class=\"NSMenuItem\" id=\"1025936716\">\n\t\t\t\t\t\t\t\t\t<reference key=\"NSMenu\" ref=\"720053764\"/>\n\t\t\t\t\t\t\t\t\t<string key=\"NSTitle\">Open Recent</string>\n\t\t\t\t\t\t\t\t\t<string key=\"NSKeyEquiv\"/>\n\t\t\t\t\t\t\t\t\t<int key=\"NSKeyEquivModMask\">1048576</int>\n\t\t\t\t\t\t\t\t\t<int key=\"NSMnemonicLoc\">2147483647</int>\n\t\t\t\t\t\t\t\t\t<reference key=\"NSOnImage\" ref=\"35465992\"/>\n\t\t\t\t\t\t\t\t\t<reference key=\"NSMixedImage\" ref=\"502551668\"/>\n\t\t\t\t\t\t\t\t\t<string key=\"NSAction\">submenuAction:</string>\n\t\t\t\t\t\t\t\t\t<object class=\"NSMenu\" key=\"NSSubmenu\" id=\"1065607017\">\n\t\t\t\t\t\t\t\t\t\t<string key=\"NSTitle\">Open Recent</string>\n\t\t\t\t\t\t\t\t\t\t<object class=\"NSMutableArray\" key=\"NSMenuItems\">\n\t\t\t\t\t\t\t\t\t\t\t<bool key=\"EncodedWithXMLCoder\">YES</bool>\n\t\t\t\t\t\t\t\t\t\t\t<object class=\"NSMenuItem\" id=\"759406840\">\n\t\t\t\t\t\t\t\t\t\t\t\t<reference key=\"NSMenu\" ref=\"1065607017\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t<string key=\"NSTitle\">Clear Menu</string>\n\t\t\t\t\t\t\t\t\t\t\t\t<string key=\"NSKeyEquiv\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t<int key=\"NSKeyEquivModMask\">1048576</int>\n\t\t\t\t\t\t\t\t\t\t\t\t<int key=\"NSMnemonicLoc\">2147483647</int>\n\t\t\t\t\t\t\t\t\t\t\t\t<reference key=\"NSOnImage\" ref=\"35465992\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t<reference key=\"NSMixedImage\" ref=\"502551668\"/>\n\t\t\t\t\t\t\t\t\t\t\t</object>\n\t\t\t\t\t\t\t\t\t\t</object>\n\t\t\t\t\t\t\t\t\t\t<string key=\"NSName\">_NSRecentDocumentsMenu</string>\n\t\t\t\t\t\t\t\t\t</object>\n\t\t\t\t\t\t\t\t</object>\n\t\t\t\t\t\t\t\t<object class=\"NSMenuItem\" id=\"425164168\">\n\t\t\t\t\t\t\t\t\t<reference key=\"NSMenu\" ref=\"720053764\"/>\n\t\t\t\t\t\t\t\t\t<bool key=\"NSIsDisabled\">YES</bool>\n\t\t\t\t\t\t\t\t\t<bool key=\"NSIsSeparator\">YES</bool>\n\t\t\t\t\t\t\t\t\t<string key=\"NSTitle\"/>\n\t\t\t\t\t\t\t\t\t<string key=\"NSKeyEquiv\"/>\n\t\t\t\t\t\t\t\t\t<int key=\"NSKeyEquivModMask\">1048576</int>\n\t\t\t\t\t\t\t\t\t<int key=\"NSMnemonicLoc\">2147483647</int>\n\t\t\t\t\t\t\t\t\t<reference key=\"NSOnImage\" ref=\"35465992\"/>\n\t\t\t\t\t\t\t\t\t<reference key=\"NSMixedImage\" ref=\"502551668\"/>\n\t\t\t\t\t\t\t\t</object>\n\t\t\t\t\t\t\t\t<object class=\"NSMenuItem\" id=\"776162233\">\n\t\t\t\t\t\t\t\t\t<reference key=\"NSMenu\" ref=\"720053764\"/>\n\t\t\t\t\t\t\t\t\t<string key=\"NSTitle\">Close</string>\n\t\t\t\t\t\t\t\t\t<string key=\"NSKeyEquiv\">w</string>\n\t\t\t\t\t\t\t\t\t<int key=\"NSKeyEquivModMask\">1048576</int>\n\t\t\t\t\t\t\t\t\t<int key=\"NSMnemonicLoc\">2147483647</int>\n\t\t\t\t\t\t\t\t\t<reference key=\"NSOnImage\" ref=\"35465992\"/>\n\t\t\t\t\t\t\t\t\t<reference key=\"NSMixedImage\" ref=\"502551668\"/>\n\t\t\t\t\t\t\t\t</object>\n\t\t\t\t\t\t\t\t<object class=\"NSMenuItem\" id=\"1023925487\">\n\t\t\t\t\t\t\t\t\t<reference key=\"NSMenu\" ref=\"720053764\"/>\n\t\t\t\t\t\t\t\t\t<string key=\"NSTitle\">Save</string>\n\t\t\t\t\t\t\t\t\t<string key=\"NSKeyEquiv\">s</string>\n\t\t\t\t\t\t\t\t\t<int key=\"NSKeyEquivModMask\">1048576</int>\n\t\t\t\t\t\t\t\t\t<int key=\"NSMnemonicLoc\">2147483647</int>\n\t\t\t\t\t\t\t\t\t<reference key=\"NSOnImage\" ref=\"35465992\"/>\n\t\t\t\t\t\t\t\t\t<reference key=\"NSMixedImage\" ref=\"502551668\"/>\n\t\t\t\t\t\t\t\t</object>\n\t\t\t\t\t\t\t\t<object class=\"NSMenuItem\" id=\"117038363\">\n\t\t\t\t\t\t\t\t\t<reference key=\"NSMenu\" ref=\"720053764\"/>\n\t\t\t\t\t\t\t\t\t<string key=\"NSTitle\">Save As…</string>\n\t\t\t\t\t\t\t\t\t<string key=\"NSKeyEquiv\">S</string>\n\t\t\t\t\t\t\t\t\t<int key=\"NSKeyEquivModMask\">1179648</int>\n\t\t\t\t\t\t\t\t\t<int key=\"NSMnemonicLoc\">2147483647</int>\n\t\t\t\t\t\t\t\t\t<reference key=\"NSOnImage\" ref=\"35465992\"/>\n\t\t\t\t\t\t\t\t\t<reference key=\"NSMixedImage\" ref=\"502551668\"/>\n\t\t\t\t\t\t\t\t</object>\n\t\t\t\t\t\t\t\t<object class=\"NSMenuItem\" id=\"579971712\">\n\t\t\t\t\t\t\t\t\t<reference key=\"NSMenu\" ref=\"720053764\"/>\n\t\t\t\t\t\t\t\t\t<string key=\"NSTitle\">Revert to Saved</string>\n\t\t\t\t\t\t\t\t\t<string key=\"NSKeyEquiv\"/>\n\t\t\t\t\t\t\t\t\t<int key=\"NSMnemonicLoc\">2147483647</int>\n\t\t\t\t\t\t\t\t\t<reference key=\"NSOnImage\" ref=\"35465992\"/>\n\t\t\t\t\t\t\t\t\t<reference key=\"NSMixedImage\" ref=\"502551668\"/>\n\t\t\t\t\t\t\t\t</object>\n\t\t\t\t\t\t\t\t<object class=\"NSMenuItem\" id=\"1010469920\">\n\t\t\t\t\t\t\t\t\t<reference key=\"NSMenu\" ref=\"720053764\"/>\n\t\t\t\t\t\t\t\t\t<bool key=\"NSIsDisabled\">YES</bool>\n\t\t\t\t\t\t\t\t\t<bool key=\"NSIsSeparator\">YES</bool>\n\t\t\t\t\t\t\t\t\t<string key=\"NSTitle\"/>\n\t\t\t\t\t\t\t\t\t<string key=\"NSKeyEquiv\"/>\n\t\t\t\t\t\t\t\t\t<int key=\"NSKeyEquivModMask\">1048576</int>\n\t\t\t\t\t\t\t\t\t<int key=\"NSMnemonicLoc\">2147483647</int>\n\t\t\t\t\t\t\t\t\t<reference key=\"NSOnImage\" ref=\"35465992\"/>\n\t\t\t\t\t\t\t\t\t<reference key=\"NSMixedImage\" ref=\"502551668\"/>\n\t\t\t\t\t\t\t\t</object>\n\t\t\t\t\t\t\t\t<object class=\"NSMenuItem\" id=\"294629803\">\n\t\t\t\t\t\t\t\t\t<reference key=\"NSMenu\" ref=\"720053764\"/>\n\t\t\t\t\t\t\t\t\t<string key=\"NSTitle\">Page Setup...</string>\n\t\t\t\t\t\t\t\t\t<string key=\"NSKeyEquiv\">P</string>\n\t\t\t\t\t\t\t\t\t<int key=\"NSKeyEquivModMask\">1179648</int>\n\t\t\t\t\t\t\t\t\t<int key=\"NSMnemonicLoc\">2147483647</int>\n\t\t\t\t\t\t\t\t\t<reference key=\"NSOnImage\" ref=\"35465992\"/>\n\t\t\t\t\t\t\t\t\t<reference key=\"NSMixedImage\" ref=\"502551668\"/>\n\t\t\t\t\t\t\t\t\t<string key=\"NSToolTip\"/>\n\t\t\t\t\t\t\t\t</object>\n\t\t\t\t\t\t\t\t<object class=\"NSMenuItem\" id=\"49223823\">\n\t\t\t\t\t\t\t\t\t<reference key=\"NSMenu\" ref=\"720053764\"/>\n\t\t\t\t\t\t\t\t\t<string key=\"NSTitle\">Print…</string>\n\t\t\t\t\t\t\t\t\t<string key=\"NSKeyEquiv\">p</string>\n\t\t\t\t\t\t\t\t\t<int key=\"NSKeyEquivModMask\">1048576</int>\n\t\t\t\t\t\t\t\t\t<int key=\"NSMnemonicLoc\">2147483647</int>\n\t\t\t\t\t\t\t\t\t<reference key=\"NSOnImage\" ref=\"35465992\"/>\n\t\t\t\t\t\t\t\t\t<reference key=\"NSMixedImage\" ref=\"502551668\"/>\n\t\t\t\t\t\t\t\t</object>\n\t\t\t\t\t\t\t</object>\n\t\t\t\t\t\t</object>\n\t\t\t\t\t</object>\n\t\t\t\t\t<object class=\"NSMenuItem\" id=\"952259628\">\n\t\t\t\t\t\t<reference key=\"NSMenu\" ref=\"649796088\"/>\n\t\t\t\t\t\t<string key=\"NSTitle\">Edit</string>\n\t\t\t\t\t\t<string key=\"NSKeyEquiv\"/>\n\t\t\t\t\t\t<int key=\"NSKeyEquivModMask\">1048576</int>\n\t\t\t\t\t\t<int key=\"NSMnemonicLoc\">2147483647</int>\n\t\t\t\t\t\t<reference key=\"NSOnImage\" ref=\"35465992\"/>\n\t\t\t\t\t\t<reference key=\"NSMixedImage\" ref=\"502551668\"/>\n\t\t\t\t\t\t<string key=\"NSAction\">submenuAction:</string>\n\t\t\t\t\t\t<object class=\"NSMenu\" key=\"NSSubmenu\" id=\"789758025\">\n\t\t\t\t\t\t\t<string key=\"NSTitle\">Edit</string>\n\t\t\t\t\t\t\t<object class=\"NSMutableArray\" key=\"NSMenuItems\">\n\t\t\t\t\t\t\t\t<bool key=\"EncodedWithXMLCoder\">YES</bool>\n\t\t\t\t\t\t\t\t<object class=\"NSMenuItem\" id=\"1058277027\">\n\t\t\t\t\t\t\t\t\t<reference key=\"NSMenu\" ref=\"789758025\"/>\n\t\t\t\t\t\t\t\t\t<string key=\"NSTitle\">Undo</string>\n\t\t\t\t\t\t\t\t\t<string key=\"NSKeyEquiv\">z</string>\n\t\t\t\t\t\t\t\t\t<int key=\"NSKeyEquivModMask\">1048576</int>\n\t\t\t\t\t\t\t\t\t<int key=\"NSMnemonicLoc\">2147483647</int>\n\t\t\t\t\t\t\t\t\t<reference key=\"NSOnImage\" ref=\"35465992\"/>\n\t\t\t\t\t\t\t\t\t<reference key=\"NSMixedImage\" ref=\"502551668\"/>\n\t\t\t\t\t\t\t\t</object>\n\t\t\t\t\t\t\t\t<object class=\"NSMenuItem\" id=\"790794224\">\n\t\t\t\t\t\t\t\t\t<reference key=\"NSMenu\" ref=\"789758025\"/>\n\t\t\t\t\t\t\t\t\t<string key=\"NSTitle\">Redo</string>\n\t\t\t\t\t\t\t\t\t<string key=\"NSKeyEquiv\">Z</string>\n\t\t\t\t\t\t\t\t\t<int key=\"NSKeyEquivModMask\">1179648</int>\n\t\t\t\t\t\t\t\t\t<int key=\"NSMnemonicLoc\">2147483647</int>\n\t\t\t\t\t\t\t\t\t<reference key=\"NSOnImage\" ref=\"35465992\"/>\n\t\t\t\t\t\t\t\t\t<reference key=\"NSMixedImage\" ref=\"502551668\"/>\n\t\t\t\t\t\t\t\t</object>\n\t\t\t\t\t\t\t\t<object class=\"NSMenuItem\" id=\"1040322652\">\n\t\t\t\t\t\t\t\t\t<reference key=\"NSMenu\" ref=\"789758025\"/>\n\t\t\t\t\t\t\t\t\t<bool key=\"NSIsDisabled\">YES</bool>\n\t\t\t\t\t\t\t\t\t<bool key=\"NSIsSeparator\">YES</bool>\n\t\t\t\t\t\t\t\t\t<string key=\"NSTitle\"/>\n\t\t\t\t\t\t\t\t\t<string key=\"NSKeyEquiv\"/>\n\t\t\t\t\t\t\t\t\t<int key=\"NSKeyEquivModMask\">1048576</int>\n\t\t\t\t\t\t\t\t\t<int key=\"NSMnemonicLoc\">2147483647</int>\n\t\t\t\t\t\t\t\t\t<reference key=\"NSOnImage\" ref=\"35465992\"/>\n\t\t\t\t\t\t\t\t\t<reference key=\"NSMixedImage\" ref=\"502551668\"/>\n\t\t\t\t\t\t\t\t</object>\n\t\t\t\t\t\t\t\t<object class=\"NSMenuItem\" id=\"296257095\">\n\t\t\t\t\t\t\t\t\t<reference key=\"NSMenu\" ref=\"789758025\"/>\n\t\t\t\t\t\t\t\t\t<string key=\"NSTitle\">Cut</string>\n\t\t\t\t\t\t\t\t\t<string key=\"NSKeyEquiv\">x</string>\n\t\t\t\t\t\t\t\t\t<int key=\"NSKeyEquivModMask\">1048576</int>\n\t\t\t\t\t\t\t\t\t<int key=\"NSMnemonicLoc\">2147483647</int>\n\t\t\t\t\t\t\t\t\t<reference key=\"NSOnImage\" ref=\"35465992\"/>\n\t\t\t\t\t\t\t\t\t<reference key=\"NSMixedImage\" ref=\"502551668\"/>\n\t\t\t\t\t\t\t\t</object>\n\t\t\t\t\t\t\t\t<object class=\"NSMenuItem\" id=\"860595796\">\n\t\t\t\t\t\t\t\t\t<reference key=\"NSMenu\" ref=\"789758025\"/>\n\t\t\t\t\t\t\t\t\t<string key=\"NSTitle\">Copy</string>\n\t\t\t\t\t\t\t\t\t<string key=\"NSKeyEquiv\">c</string>\n\t\t\t\t\t\t\t\t\t<int key=\"NSKeyEquivModMask\">1048576</int>\n\t\t\t\t\t\t\t\t\t<int key=\"NSMnemonicLoc\">2147483647</int>\n\t\t\t\t\t\t\t\t\t<reference key=\"NSOnImage\" ref=\"35465992\"/>\n\t\t\t\t\t\t\t\t\t<reference key=\"NSMixedImage\" ref=\"502551668\"/>\n\t\t\t\t\t\t\t\t</object>\n\t\t\t\t\t\t\t\t<object class=\"NSMenuItem\" id=\"29853731\">\n\t\t\t\t\t\t\t\t\t<reference key=\"NSMenu\" ref=\"789758025\"/>\n\t\t\t\t\t\t\t\t\t<string key=\"NSTitle\">Paste</string>\n\t\t\t\t\t\t\t\t\t<string key=\"NSKeyEquiv\">v</string>\n\t\t\t\t\t\t\t\t\t<int key=\"NSKeyEquivModMask\">1048576</int>\n\t\t\t\t\t\t\t\t\t<int key=\"NSMnemonicLoc\">2147483647</int>\n\t\t\t\t\t\t\t\t\t<reference key=\"NSOnImage\" ref=\"35465992\"/>\n\t\t\t\t\t\t\t\t\t<reference key=\"NSMixedImage\" ref=\"502551668\"/>\n\t\t\t\t\t\t\t\t</object>\n\t\t\t\t\t\t\t\t<object class=\"NSMenuItem\" id=\"82994268\">\n\t\t\t\t\t\t\t\t\t<reference key=\"NSMenu\" ref=\"789758025\"/>\n\t\t\t\t\t\t\t\t\t<string key=\"NSTitle\">Paste and Match Style</string>\n\t\t\t\t\t\t\t\t\t<string key=\"NSKeyEquiv\">V</string>\n\t\t\t\t\t\t\t\t\t<int key=\"NSKeyEquivModMask\">1572864</int>\n\t\t\t\t\t\t\t\t\t<int key=\"NSMnemonicLoc\">2147483647</int>\n\t\t\t\t\t\t\t\t\t<reference key=\"NSOnImage\" ref=\"35465992\"/>\n\t\t\t\t\t\t\t\t\t<reference key=\"NSMixedImage\" ref=\"502551668\"/>\n\t\t\t\t\t\t\t\t</object>\n\t\t\t\t\t\t\t\t<object class=\"NSMenuItem\" id=\"437104165\">\n\t\t\t\t\t\t\t\t\t<reference key=\"NSMenu\" ref=\"789758025\"/>\n\t\t\t\t\t\t\t\t\t<string key=\"NSTitle\">Delete</string>\n\t\t\t\t\t\t\t\t\t<string key=\"NSKeyEquiv\"/>\n\t\t\t\t\t\t\t\t\t<int key=\"NSKeyEquivModMask\">1048576</int>\n\t\t\t\t\t\t\t\t\t<int key=\"NSMnemonicLoc\">2147483647</int>\n\t\t\t\t\t\t\t\t\t<reference key=\"NSOnImage\" ref=\"35465992\"/>\n\t\t\t\t\t\t\t\t\t<reference key=\"NSMixedImage\" ref=\"502551668\"/>\n\t\t\t\t\t\t\t\t</object>\n\t\t\t\t\t\t\t\t<object class=\"NSMenuItem\" id=\"583158037\">\n\t\t\t\t\t\t\t\t\t<reference key=\"NSMenu\" ref=\"789758025\"/>\n\t\t\t\t\t\t\t\t\t<string key=\"NSTitle\">Select All</string>\n\t\t\t\t\t\t\t\t\t<string key=\"NSKeyEquiv\">a</string>\n\t\t\t\t\t\t\t\t\t<int key=\"NSKeyEquivModMask\">1048576</int>\n\t\t\t\t\t\t\t\t\t<int key=\"NSMnemonicLoc\">2147483647</int>\n\t\t\t\t\t\t\t\t\t<reference key=\"NSOnImage\" ref=\"35465992\"/>\n\t\t\t\t\t\t\t\t\t<reference key=\"NSMixedImage\" ref=\"502551668\"/>\n\t\t\t\t\t\t\t\t</object>\n\t\t\t\t\t\t\t\t<object class=\"NSMenuItem\" id=\"212016141\">\n\t\t\t\t\t\t\t\t\t<reference key=\"NSMenu\" ref=\"789758025\"/>\n\t\t\t\t\t\t\t\t\t<bool key=\"NSIsDisabled\">YES</bool>\n\t\t\t\t\t\t\t\t\t<bool key=\"NSIsSeparator\">YES</bool>\n\t\t\t\t\t\t\t\t\t<string key=\"NSTitle\"/>\n\t\t\t\t\t\t\t\t\t<string key=\"NSKeyEquiv\"/>\n\t\t\t\t\t\t\t\t\t<int key=\"NSKeyEquivModMask\">1048576</int>\n\t\t\t\t\t\t\t\t\t<int key=\"NSMnemonicLoc\">2147483647</int>\n\t\t\t\t\t\t\t\t\t<reference key=\"NSOnImage\" ref=\"35465992\"/>\n\t\t\t\t\t\t\t\t\t<reference key=\"NSMixedImage\" ref=\"502551668\"/>\n\t\t\t\t\t\t\t\t</object>\n\t\t\t\t\t\t\t\t<object class=\"NSMenuItem\" id=\"892235320\">\n\t\t\t\t\t\t\t\t\t<reference key=\"NSMenu\" ref=\"789758025\"/>\n\t\t\t\t\t\t\t\t\t<string key=\"NSTitle\">Find</string>\n\t\t\t\t\t\t\t\t\t<string key=\"NSKeyEquiv\"/>\n\t\t\t\t\t\t\t\t\t<int key=\"NSKeyEquivModMask\">1048576</int>\n\t\t\t\t\t\t\t\t\t<int key=\"NSMnemonicLoc\">2147483647</int>\n\t\t\t\t\t\t\t\t\t<reference key=\"NSOnImage\" ref=\"35465992\"/>\n\t\t\t\t\t\t\t\t\t<reference key=\"NSMixedImage\" ref=\"502551668\"/>\n\t\t\t\t\t\t\t\t\t<string key=\"NSAction\">submenuAction:</string>\n\t\t\t\t\t\t\t\t\t<object class=\"NSMenu\" key=\"NSSubmenu\" id=\"963351320\">\n\t\t\t\t\t\t\t\t\t\t<string key=\"NSTitle\">Find</string>\n\t\t\t\t\t\t\t\t\t\t<object class=\"NSMutableArray\" key=\"NSMenuItems\">\n\t\t\t\t\t\t\t\t\t\t\t<bool key=\"EncodedWithXMLCoder\">YES</bool>\n\t\t\t\t\t\t\t\t\t\t\t<object class=\"NSMenuItem\" id=\"447796847\">\n\t\t\t\t\t\t\t\t\t\t\t\t<reference key=\"NSMenu\" ref=\"963351320\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t<string key=\"NSTitle\">Find…</string>\n\t\t\t\t\t\t\t\t\t\t\t\t<string key=\"NSKeyEquiv\">f</string>\n\t\t\t\t\t\t\t\t\t\t\t\t<int key=\"NSKeyEquivModMask\">1048576</int>\n\t\t\t\t\t\t\t\t\t\t\t\t<int key=\"NSMnemonicLoc\">2147483647</int>\n\t\t\t\t\t\t\t\t\t\t\t\t<reference key=\"NSOnImage\" ref=\"35465992\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t<reference key=\"NSMixedImage\" ref=\"502551668\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t<int key=\"NSTag\">1</int>\n\t\t\t\t\t\t\t\t\t\t\t</object>\n\t\t\t\t\t\t\t\t\t\t\t<object class=\"NSMenuItem\" id=\"326711663\">\n\t\t\t\t\t\t\t\t\t\t\t\t<reference key=\"NSMenu\" ref=\"963351320\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t<string key=\"NSTitle\">Find Next</string>\n\t\t\t\t\t\t\t\t\t\t\t\t<string key=\"NSKeyEquiv\">g</string>\n\t\t\t\t\t\t\t\t\t\t\t\t<int key=\"NSKeyEquivModMask\">1048576</int>\n\t\t\t\t\t\t\t\t\t\t\t\t<int key=\"NSMnemonicLoc\">2147483647</int>\n\t\t\t\t\t\t\t\t\t\t\t\t<reference key=\"NSOnImage\" ref=\"35465992\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t<reference key=\"NSMixedImage\" ref=\"502551668\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t<int key=\"NSTag\">2</int>\n\t\t\t\t\t\t\t\t\t\t\t</object>\n\t\t\t\t\t\t\t\t\t\t\t<object class=\"NSMenuItem\" id=\"270902937\">\n\t\t\t\t\t\t\t\t\t\t\t\t<reference key=\"NSMenu\" ref=\"963351320\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t<string key=\"NSTitle\">Find Previous</string>\n\t\t\t\t\t\t\t\t\t\t\t\t<string key=\"NSKeyEquiv\">G</string>\n\t\t\t\t\t\t\t\t\t\t\t\t<int key=\"NSKeyEquivModMask\">1179648</int>\n\t\t\t\t\t\t\t\t\t\t\t\t<int key=\"NSMnemonicLoc\">2147483647</int>\n\t\t\t\t\t\t\t\t\t\t\t\t<reference key=\"NSOnImage\" ref=\"35465992\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t<reference key=\"NSMixedImage\" ref=\"502551668\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t<int key=\"NSTag\">3</int>\n\t\t\t\t\t\t\t\t\t\t\t</object>\n\t\t\t\t\t\t\t\t\t\t\t<object class=\"NSMenuItem\" id=\"159080638\">\n\t\t\t\t\t\t\t\t\t\t\t\t<reference key=\"NSMenu\" ref=\"963351320\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t<string key=\"NSTitle\">Use Selection for Find</string>\n\t\t\t\t\t\t\t\t\t\t\t\t<string key=\"NSKeyEquiv\">e</string>\n\t\t\t\t\t\t\t\t\t\t\t\t<int key=\"NSKeyEquivModMask\">1048576</int>\n\t\t\t\t\t\t\t\t\t\t\t\t<int key=\"NSMnemonicLoc\">2147483647</int>\n\t\t\t\t\t\t\t\t\t\t\t\t<reference key=\"NSOnImage\" ref=\"35465992\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t<reference key=\"NSMixedImage\" ref=\"502551668\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t<int key=\"NSTag\">7</int>\n\t\t\t\t\t\t\t\t\t\t\t</object>\n\t\t\t\t\t\t\t\t\t\t\t<object class=\"NSMenuItem\" id=\"88285865\">\n\t\t\t\t\t\t\t\t\t\t\t\t<reference key=\"NSMenu\" ref=\"963351320\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t<string key=\"NSTitle\">Jump to Selection</string>\n\t\t\t\t\t\t\t\t\t\t\t\t<string key=\"NSKeyEquiv\">j</string>\n\t\t\t\t\t\t\t\t\t\t\t\t<int key=\"NSKeyEquivModMask\">1048576</int>\n\t\t\t\t\t\t\t\t\t\t\t\t<int key=\"NSMnemonicLoc\">2147483647</int>\n\t\t\t\t\t\t\t\t\t\t\t\t<reference key=\"NSOnImage\" ref=\"35465992\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t<reference key=\"NSMixedImage\" ref=\"502551668\"/>\n\t\t\t\t\t\t\t\t\t\t\t</object>\n\t\t\t\t\t\t\t\t\t\t</object>\n\t\t\t\t\t\t\t\t\t</object>\n\t\t\t\t\t\t\t\t</object>\n\t\t\t\t\t\t\t\t<object class=\"NSMenuItem\" id=\"972420730\">\n\t\t\t\t\t\t\t\t\t<reference key=\"NSMenu\" ref=\"789758025\"/>\n\t\t\t\t\t\t\t\t\t<string key=\"NSTitle\">Spelling and Grammar</string>\n\t\t\t\t\t\t\t\t\t<string key=\"NSKeyEquiv\"/>\n\t\t\t\t\t\t\t\t\t<int key=\"NSKeyEquivModMask\">1048576</int>\n\t\t\t\t\t\t\t\t\t<int key=\"NSMnemonicLoc\">2147483647</int>\n\t\t\t\t\t\t\t\t\t<reference key=\"NSOnImage\" ref=\"35465992\"/>\n\t\t\t\t\t\t\t\t\t<reference key=\"NSMixedImage\" ref=\"502551668\"/>\n\t\t\t\t\t\t\t\t\t<string key=\"NSAction\">submenuAction:</string>\n\t\t\t\t\t\t\t\t\t<object class=\"NSMenu\" key=\"NSSubmenu\" id=\"769623530\">\n\t\t\t\t\t\t\t\t\t\t<string key=\"NSTitle\">Spelling and Grammar</string>\n\t\t\t\t\t\t\t\t\t\t<object class=\"NSMutableArray\" key=\"NSMenuItems\">\n\t\t\t\t\t\t\t\t\t\t\t<bool key=\"EncodedWithXMLCoder\">YES</bool>\n\t\t\t\t\t\t\t\t\t\t\t<object class=\"NSMenuItem\" id=\"679648819\">\n\t\t\t\t\t\t\t\t\t\t\t\t<reference key=\"NSMenu\" ref=\"769623530\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t<string key=\"NSTitle\">Show Spelling and Grammar</string>\n\t\t\t\t\t\t\t\t\t\t\t\t<string key=\"NSKeyEquiv\">:</string>\n\t\t\t\t\t\t\t\t\t\t\t\t<int key=\"NSKeyEquivModMask\">1048576</int>\n\t\t\t\t\t\t\t\t\t\t\t\t<int key=\"NSMnemonicLoc\">2147483647</int>\n\t\t\t\t\t\t\t\t\t\t\t\t<reference key=\"NSOnImage\" ref=\"35465992\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t<reference key=\"NSMixedImage\" ref=\"502551668\"/>\n\t\t\t\t\t\t\t\t\t\t\t</object>\n\t\t\t\t\t\t\t\t\t\t\t<object class=\"NSMenuItem\" id=\"96193923\">\n\t\t\t\t\t\t\t\t\t\t\t\t<reference key=\"NSMenu\" ref=\"769623530\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t<string key=\"NSTitle\">Check Document Now</string>\n\t\t\t\t\t\t\t\t\t\t\t\t<string key=\"NSKeyEquiv\">;</string>\n\t\t\t\t\t\t\t\t\t\t\t\t<int key=\"NSKeyEquivModMask\">1048576</int>\n\t\t\t\t\t\t\t\t\t\t\t\t<int key=\"NSMnemonicLoc\">2147483647</int>\n\t\t\t\t\t\t\t\t\t\t\t\t<reference key=\"NSOnImage\" ref=\"35465992\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t<reference key=\"NSMixedImage\" ref=\"502551668\"/>\n\t\t\t\t\t\t\t\t\t\t\t</object>\n\t\t\t\t\t\t\t\t\t\t\t<object class=\"NSMenuItem\" id=\"859480356\">\n\t\t\t\t\t\t\t\t\t\t\t\t<reference key=\"NSMenu\" ref=\"769623530\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t<bool key=\"NSIsDisabled\">YES</bool>\n\t\t\t\t\t\t\t\t\t\t\t\t<bool key=\"NSIsSeparator\">YES</bool>\n\t\t\t\t\t\t\t\t\t\t\t\t<string key=\"NSTitle\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t<string key=\"NSKeyEquiv\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t<int key=\"NSMnemonicLoc\">2147483647</int>\n\t\t\t\t\t\t\t\t\t\t\t\t<reference key=\"NSOnImage\" ref=\"35465992\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t<reference key=\"NSMixedImage\" ref=\"502551668\"/>\n\t\t\t\t\t\t\t\t\t\t\t</object>\n\t\t\t\t\t\t\t\t\t\t\t<object class=\"NSMenuItem\" id=\"948374510\">\n\t\t\t\t\t\t\t\t\t\t\t\t<reference key=\"NSMenu\" ref=\"769623530\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t<string key=\"NSTitle\">Check Spelling While Typing</string>\n\t\t\t\t\t\t\t\t\t\t\t\t<string key=\"NSKeyEquiv\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t<int key=\"NSKeyEquivModMask\">1048576</int>\n\t\t\t\t\t\t\t\t\t\t\t\t<int key=\"NSMnemonicLoc\">2147483647</int>\n\t\t\t\t\t\t\t\t\t\t\t\t<reference key=\"NSOnImage\" ref=\"35465992\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t<reference key=\"NSMixedImage\" ref=\"502551668\"/>\n\t\t\t\t\t\t\t\t\t\t\t</object>\n\t\t\t\t\t\t\t\t\t\t\t<object class=\"NSMenuItem\" id=\"967646866\">\n\t\t\t\t\t\t\t\t\t\t\t\t<reference key=\"NSMenu\" ref=\"769623530\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t<string key=\"NSTitle\">Check Grammar With Spelling</string>\n\t\t\t\t\t\t\t\t\t\t\t\t<string key=\"NSKeyEquiv\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t<int key=\"NSKeyEquivModMask\">1048576</int>\n\t\t\t\t\t\t\t\t\t\t\t\t<int key=\"NSMnemonicLoc\">2147483647</int>\n\t\t\t\t\t\t\t\t\t\t\t\t<reference key=\"NSOnImage\" ref=\"35465992\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t<reference key=\"NSMixedImage\" ref=\"502551668\"/>\n\t\t\t\t\t\t\t\t\t\t\t</object>\n\t\t\t\t\t\t\t\t\t\t\t<object class=\"NSMenuItem\" id=\"795346622\">\n\t\t\t\t\t\t\t\t\t\t\t\t<reference key=\"NSMenu\" ref=\"769623530\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t<string key=\"NSTitle\">Correct Spelling Automatically</string>\n\t\t\t\t\t\t\t\t\t\t\t\t<string key=\"NSKeyEquiv\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t<int key=\"NSMnemonicLoc\">2147483647</int>\n\t\t\t\t\t\t\t\t\t\t\t\t<reference key=\"NSOnImage\" ref=\"35465992\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t<reference key=\"NSMixedImage\" ref=\"502551668\"/>\n\t\t\t\t\t\t\t\t\t\t\t</object>\n\t\t\t\t\t\t\t\t\t\t</object>\n\t\t\t\t\t\t\t\t\t</object>\n\t\t\t\t\t\t\t\t</object>\n\t\t\t\t\t\t\t\t<object class=\"NSMenuItem\" id=\"507821607\">\n\t\t\t\t\t\t\t\t\t<reference key=\"NSMenu\" ref=\"789758025\"/>\n\t\t\t\t\t\t\t\t\t<string key=\"NSTitle\">Substitutions</string>\n\t\t\t\t\t\t\t\t\t<string key=\"NSKeyEquiv\"/>\n\t\t\t\t\t\t\t\t\t<int key=\"NSKeyEquivModMask\">1048576</int>\n\t\t\t\t\t\t\t\t\t<int key=\"NSMnemonicLoc\">2147483647</int>\n\t\t\t\t\t\t\t\t\t<reference key=\"NSOnImage\" ref=\"35465992\"/>\n\t\t\t\t\t\t\t\t\t<reference key=\"NSMixedImage\" ref=\"502551668\"/>\n\t\t\t\t\t\t\t\t\t<string key=\"NSAction\">submenuAction:</string>\n\t\t\t\t\t\t\t\t\t<object class=\"NSMenu\" key=\"NSSubmenu\" id=\"698887838\">\n\t\t\t\t\t\t\t\t\t\t<string key=\"NSTitle\">Substitutions</string>\n\t\t\t\t\t\t\t\t\t\t<object class=\"NSMutableArray\" key=\"NSMenuItems\">\n\t\t\t\t\t\t\t\t\t\t\t<bool key=\"EncodedWithXMLCoder\">YES</bool>\n\t\t\t\t\t\t\t\t\t\t\t<object class=\"NSMenuItem\" id=\"65139061\">\n\t\t\t\t\t\t\t\t\t\t\t\t<reference key=\"NSMenu\" ref=\"698887838\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t<string key=\"NSTitle\">Show Substitutions</string>\n\t\t\t\t\t\t\t\t\t\t\t\t<string key=\"NSKeyEquiv\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t<int key=\"NSMnemonicLoc\">2147483647</int>\n\t\t\t\t\t\t\t\t\t\t\t\t<reference key=\"NSOnImage\" ref=\"35465992\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t<reference key=\"NSMixedImage\" ref=\"502551668\"/>\n\t\t\t\t\t\t\t\t\t\t\t</object>\n\t\t\t\t\t\t\t\t\t\t\t<object class=\"NSMenuItem\" id=\"19036812\">\n\t\t\t\t\t\t\t\t\t\t\t\t<reference key=\"NSMenu\" ref=\"698887838\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t<bool key=\"NSIsDisabled\">YES</bool>\n\t\t\t\t\t\t\t\t\t\t\t\t<bool key=\"NSIsSeparator\">YES</bool>\n\t\t\t\t\t\t\t\t\t\t\t\t<string key=\"NSTitle\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t<string key=\"NSKeyEquiv\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t<int key=\"NSMnemonicLoc\">2147483647</int>\n\t\t\t\t\t\t\t\t\t\t\t\t<reference key=\"NSOnImage\" ref=\"35465992\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t<reference key=\"NSMixedImage\" ref=\"502551668\"/>\n\t\t\t\t\t\t\t\t\t\t\t</object>\n\t\t\t\t\t\t\t\t\t\t\t<object class=\"NSMenuItem\" id=\"605118523\">\n\t\t\t\t\t\t\t\t\t\t\t\t<reference key=\"NSMenu\" ref=\"698887838\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t<string key=\"NSTitle\">Smart Copy/Paste</string>\n\t\t\t\t\t\t\t\t\t\t\t\t<string key=\"NSKeyEquiv\">f</string>\n\t\t\t\t\t\t\t\t\t\t\t\t<int key=\"NSKeyEquivModMask\">1048576</int>\n\t\t\t\t\t\t\t\t\t\t\t\t<int key=\"NSMnemonicLoc\">2147483647</int>\n\t\t\t\t\t\t\t\t\t\t\t\t<reference key=\"NSOnImage\" ref=\"35465992\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t<reference key=\"NSMixedImage\" ref=\"502551668\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t<int key=\"NSTag\">1</int>\n\t\t\t\t\t\t\t\t\t\t\t</object>\n\t\t\t\t\t\t\t\t\t\t\t<object class=\"NSMenuItem\" id=\"197661976\">\n\t\t\t\t\t\t\t\t\t\t\t\t<reference key=\"NSMenu\" ref=\"698887838\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t<string key=\"NSTitle\">Smart Quotes</string>\n\t\t\t\t\t\t\t\t\t\t\t\t<string key=\"NSKeyEquiv\">g</string>\n\t\t\t\t\t\t\t\t\t\t\t\t<int key=\"NSKeyEquivModMask\">1048576</int>\n\t\t\t\t\t\t\t\t\t\t\t\t<int key=\"NSMnemonicLoc\">2147483647</int>\n\t\t\t\t\t\t\t\t\t\t\t\t<reference key=\"NSOnImage\" ref=\"35465992\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t<reference key=\"NSMixedImage\" ref=\"502551668\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t<int key=\"NSTag\">2</int>\n\t\t\t\t\t\t\t\t\t\t\t</object>\n\t\t\t\t\t\t\t\t\t\t\t<object class=\"NSMenuItem\" id=\"672708820\">\n\t\t\t\t\t\t\t\t\t\t\t\t<reference key=\"NSMenu\" ref=\"698887838\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t<string key=\"NSTitle\">Smart Dashes</string>\n\t\t\t\t\t\t\t\t\t\t\t\t<string key=\"NSKeyEquiv\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t<int key=\"NSMnemonicLoc\">2147483647</int>\n\t\t\t\t\t\t\t\t\t\t\t\t<reference key=\"NSOnImage\" ref=\"35465992\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t<reference key=\"NSMixedImage\" ref=\"502551668\"/>\n\t\t\t\t\t\t\t\t\t\t\t</object>\n\t\t\t\t\t\t\t\t\t\t\t<object class=\"NSMenuItem\" id=\"708854459\">\n\t\t\t\t\t\t\t\t\t\t\t\t<reference key=\"NSMenu\" ref=\"698887838\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t<string key=\"NSTitle\">Smart Links</string>\n\t\t\t\t\t\t\t\t\t\t\t\t<string key=\"NSKeyEquiv\">G</string>\n\t\t\t\t\t\t\t\t\t\t\t\t<int key=\"NSKeyEquivModMask\">1179648</int>\n\t\t\t\t\t\t\t\t\t\t\t\t<int key=\"NSMnemonicLoc\">2147483647</int>\n\t\t\t\t\t\t\t\t\t\t\t\t<reference key=\"NSOnImage\" ref=\"35465992\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t<reference key=\"NSMixedImage\" ref=\"502551668\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t<int key=\"NSTag\">3</int>\n\t\t\t\t\t\t\t\t\t\t\t</object>\n\t\t\t\t\t\t\t\t\t\t\t<object class=\"NSMenuItem\" id=\"537092702\">\n\t\t\t\t\t\t\t\t\t\t\t\t<reference key=\"NSMenu\" ref=\"698887838\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t<string key=\"NSTitle\">Text Replacement</string>\n\t\t\t\t\t\t\t\t\t\t\t\t<string key=\"NSKeyEquiv\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t<int key=\"NSMnemonicLoc\">2147483647</int>\n\t\t\t\t\t\t\t\t\t\t\t\t<reference key=\"NSOnImage\" ref=\"35465992\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t<reference key=\"NSMixedImage\" ref=\"502551668\"/>\n\t\t\t\t\t\t\t\t\t\t\t</object>\n\t\t\t\t\t\t\t\t\t\t</object>\n\t\t\t\t\t\t\t\t\t</object>\n\t\t\t\t\t\t\t\t</object>\n\t\t\t\t\t\t\t\t<object class=\"NSMenuItem\" id=\"288088188\">\n\t\t\t\t\t\t\t\t\t<reference key=\"NSMenu\" ref=\"789758025\"/>\n\t\t\t\t\t\t\t\t\t<string key=\"NSTitle\">Transformations</string>\n\t\t\t\t\t\t\t\t\t<string key=\"NSKeyEquiv\"/>\n\t\t\t\t\t\t\t\t\t<int key=\"NSMnemonicLoc\">2147483647</int>\n\t\t\t\t\t\t\t\t\t<reference key=\"NSOnImage\" ref=\"35465992\"/>\n\t\t\t\t\t\t\t\t\t<reference key=\"NSMixedImage\" ref=\"502551668\"/>\n\t\t\t\t\t\t\t\t\t<string key=\"NSAction\">submenuAction:</string>\n\t\t\t\t\t\t\t\t\t<object class=\"NSMenu\" key=\"NSSubmenu\" id=\"579392910\">\n\t\t\t\t\t\t\t\t\t\t<string key=\"NSTitle\">Transformations</string>\n\t\t\t\t\t\t\t\t\t\t<object class=\"NSMutableArray\" key=\"NSMenuItems\">\n\t\t\t\t\t\t\t\t\t\t\t<bool key=\"EncodedWithXMLCoder\">YES</bool>\n\t\t\t\t\t\t\t\t\t\t\t<object class=\"NSMenuItem\" id=\"1060694897\">\n\t\t\t\t\t\t\t\t\t\t\t\t<reference key=\"NSMenu\" ref=\"579392910\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t<string key=\"NSTitle\">Make Upper Case</string>\n\t\t\t\t\t\t\t\t\t\t\t\t<string key=\"NSKeyEquiv\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t<int key=\"NSMnemonicLoc\">2147483647</int>\n\t\t\t\t\t\t\t\t\t\t\t\t<reference key=\"NSOnImage\" ref=\"35465992\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t<reference key=\"NSMixedImage\" ref=\"502551668\"/>\n\t\t\t\t\t\t\t\t\t\t\t</object>\n\t\t\t\t\t\t\t\t\t\t\t<object class=\"NSMenuItem\" id=\"879586729\">\n\t\t\t\t\t\t\t\t\t\t\t\t<reference key=\"NSMenu\" ref=\"579392910\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t<string key=\"NSTitle\">Make Lower Case</string>\n\t\t\t\t\t\t\t\t\t\t\t\t<string key=\"NSKeyEquiv\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t<int key=\"NSMnemonicLoc\">2147483647</int>\n\t\t\t\t\t\t\t\t\t\t\t\t<reference key=\"NSOnImage\" ref=\"35465992\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t<reference key=\"NSMixedImage\" ref=\"502551668\"/>\n\t\t\t\t\t\t\t\t\t\t\t</object>\n\t\t\t\t\t\t\t\t\t\t\t<object class=\"NSMenuItem\" id=\"56570060\">\n\t\t\t\t\t\t\t\t\t\t\t\t<reference key=\"NSMenu\" ref=\"579392910\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t<string key=\"NSTitle\">Capitalize</string>\n\t\t\t\t\t\t\t\t\t\t\t\t<string key=\"NSKeyEquiv\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t<int key=\"NSMnemonicLoc\">2147483647</int>\n\t\t\t\t\t\t\t\t\t\t\t\t<reference key=\"NSOnImage\" ref=\"35465992\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t<reference key=\"NSMixedImage\" ref=\"502551668\"/>\n\t\t\t\t\t\t\t\t\t\t\t</object>\n\t\t\t\t\t\t\t\t\t\t</object>\n\t\t\t\t\t\t\t\t\t</object>\n\t\t\t\t\t\t\t\t</object>\n\t\t\t\t\t\t\t\t<object class=\"NSMenuItem\" id=\"676164635\">\n\t\t\t\t\t\t\t\t\t<reference key=\"NSMenu\" ref=\"789758025\"/>\n\t\t\t\t\t\t\t\t\t<string key=\"NSTitle\">Speech</string>\n\t\t\t\t\t\t\t\t\t<string key=\"NSKeyEquiv\"/>\n\t\t\t\t\t\t\t\t\t<int key=\"NSKeyEquivModMask\">1048576</int>\n\t\t\t\t\t\t\t\t\t<int key=\"NSMnemonicLoc\">2147483647</int>\n\t\t\t\t\t\t\t\t\t<reference key=\"NSOnImage\" ref=\"35465992\"/>\n\t\t\t\t\t\t\t\t\t<reference key=\"NSMixedImage\" ref=\"502551668\"/>\n\t\t\t\t\t\t\t\t\t<string key=\"NSAction\">submenuAction:</string>\n\t\t\t\t\t\t\t\t\t<object class=\"NSMenu\" key=\"NSSubmenu\" id=\"785027613\">\n\t\t\t\t\t\t\t\t\t\t<string key=\"NSTitle\">Speech</string>\n\t\t\t\t\t\t\t\t\t\t<object class=\"NSMutableArray\" key=\"NSMenuItems\">\n\t\t\t\t\t\t\t\t\t\t\t<bool key=\"EncodedWithXMLCoder\">YES</bool>\n\t\t\t\t\t\t\t\t\t\t\t<object class=\"NSMenuItem\" id=\"731782645\">\n\t\t\t\t\t\t\t\t\t\t\t\t<reference key=\"NSMenu\" ref=\"785027613\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t<string key=\"NSTitle\">Start Speaking</string>\n\t\t\t\t\t\t\t\t\t\t\t\t<string key=\"NSKeyEquiv\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t<int key=\"NSKeyEquivModMask\">1048576</int>\n\t\t\t\t\t\t\t\t\t\t\t\t<int key=\"NSMnemonicLoc\">2147483647</int>\n\t\t\t\t\t\t\t\t\t\t\t\t<reference key=\"NSOnImage\" ref=\"35465992\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t<reference key=\"NSMixedImage\" ref=\"502551668\"/>\n\t\t\t\t\t\t\t\t\t\t\t</object>\n\t\t\t\t\t\t\t\t\t\t\t<object class=\"NSMenuItem\" id=\"680220178\">\n\t\t\t\t\t\t\t\t\t\t\t\t<reference key=\"NSMenu\" ref=\"785027613\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t<string key=\"NSTitle\">Stop Speaking</string>\n\t\t\t\t\t\t\t\t\t\t\t\t<string key=\"NSKeyEquiv\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t<int key=\"NSKeyEquivModMask\">1048576</int>\n\t\t\t\t\t\t\t\t\t\t\t\t<int key=\"NSMnemonicLoc\">2147483647</int>\n\t\t\t\t\t\t\t\t\t\t\t\t<reference key=\"NSOnImage\" ref=\"35465992\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t<reference key=\"NSMixedImage\" ref=\"502551668\"/>\n\t\t\t\t\t\t\t\t\t\t\t</object>\n\t\t\t\t\t\t\t\t\t\t</object>\n\t\t\t\t\t\t\t\t\t</object>\n\t\t\t\t\t\t\t\t</object>\n\t\t\t\t\t\t\t</object>\n\t\t\t\t\t\t</object>\n\t\t\t\t\t</object>\n\t\t\t\t\t<object class=\"NSMenuItem\" id=\"302598603\">\n\t\t\t\t\t\t<reference key=\"NSMenu\" ref=\"649796088\"/>\n\t\t\t\t\t\t<string key=\"NSTitle\">Format</string>\n\t\t\t\t\t\t<string key=\"NSKeyEquiv\"/>\n\t\t\t\t\t\t<int key=\"NSMnemonicLoc\">2147483647</int>\n\t\t\t\t\t\t<reference key=\"NSOnImage\" ref=\"35465992\"/>\n\t\t\t\t\t\t<reference key=\"NSMixedImage\" ref=\"502551668\"/>\n\t\t\t\t\t\t<string key=\"NSAction\">submenuAction:</string>\n\t\t\t\t\t\t<object class=\"NSMenu\" key=\"NSSubmenu\" id=\"941447902\">\n\t\t\t\t\t\t\t<string key=\"NSTitle\">Format</string>\n\t\t\t\t\t\t\t<object class=\"NSMutableArray\" key=\"NSMenuItems\">\n\t\t\t\t\t\t\t\t<bool key=\"EncodedWithXMLCoder\">YES</bool>\n\t\t\t\t\t\t\t\t<object class=\"NSMenuItem\" id=\"792887677\">\n\t\t\t\t\t\t\t\t\t<reference key=\"NSMenu\" ref=\"941447902\"/>\n\t\t\t\t\t\t\t\t\t<string key=\"NSTitle\">Font</string>\n\t\t\t\t\t\t\t\t\t<string key=\"NSKeyEquiv\"/>\n\t\t\t\t\t\t\t\t\t<int key=\"NSMnemonicLoc\">2147483647</int>\n\t\t\t\t\t\t\t\t\t<reference key=\"NSOnImage\" ref=\"35465992\"/>\n\t\t\t\t\t\t\t\t\t<reference key=\"NSMixedImage\" ref=\"502551668\"/>\n\t\t\t\t\t\t\t\t\t<string key=\"NSAction\">submenuAction:</string>\n\t\t\t\t\t\t\t\t\t<object class=\"NSMenu\" key=\"NSSubmenu\" id=\"786677654\">\n\t\t\t\t\t\t\t\t\t\t<string key=\"NSTitle\">Font</string>\n\t\t\t\t\t\t\t\t\t\t<object class=\"NSMutableArray\" key=\"NSMenuItems\">\n\t\t\t\t\t\t\t\t\t\t\t<bool key=\"EncodedWithXMLCoder\">YES</bool>\n\t\t\t\t\t\t\t\t\t\t\t<object class=\"NSMenuItem\" id=\"159677712\">\n\t\t\t\t\t\t\t\t\t\t\t\t<reference key=\"NSMenu\" ref=\"786677654\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t<string key=\"NSTitle\">Show Fonts</string>\n\t\t\t\t\t\t\t\t\t\t\t\t<string key=\"NSKeyEquiv\">t</string>\n\t\t\t\t\t\t\t\t\t\t\t\t<int key=\"NSKeyEquivModMask\">1048576</int>\n\t\t\t\t\t\t\t\t\t\t\t\t<int key=\"NSMnemonicLoc\">2147483647</int>\n\t\t\t\t\t\t\t\t\t\t\t\t<reference key=\"NSOnImage\" ref=\"35465992\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t<reference key=\"NSMixedImage\" ref=\"502551668\"/>\n\t\t\t\t\t\t\t\t\t\t\t</object>\n\t\t\t\t\t\t\t\t\t\t\t<object class=\"NSMenuItem\" id=\"305399458\">\n\t\t\t\t\t\t\t\t\t\t\t\t<reference key=\"NSMenu\" ref=\"786677654\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t<string key=\"NSTitle\">Bold</string>\n\t\t\t\t\t\t\t\t\t\t\t\t<string key=\"NSKeyEquiv\">b</string>\n\t\t\t\t\t\t\t\t\t\t\t\t<int key=\"NSKeyEquivModMask\">1048576</int>\n\t\t\t\t\t\t\t\t\t\t\t\t<int key=\"NSMnemonicLoc\">2147483647</int>\n\t\t\t\t\t\t\t\t\t\t\t\t<reference key=\"NSOnImage\" ref=\"35465992\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t<reference key=\"NSMixedImage\" ref=\"502551668\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t<int key=\"NSTag\">2</int>\n\t\t\t\t\t\t\t\t\t\t\t</object>\n\t\t\t\t\t\t\t\t\t\t\t<object class=\"NSMenuItem\" id=\"814362025\">\n\t\t\t\t\t\t\t\t\t\t\t\t<reference key=\"NSMenu\" ref=\"786677654\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t<string key=\"NSTitle\">Italic</string>\n\t\t\t\t\t\t\t\t\t\t\t\t<string key=\"NSKeyEquiv\">i</string>\n\t\t\t\t\t\t\t\t\t\t\t\t<int key=\"NSKeyEquivModMask\">1048576</int>\n\t\t\t\t\t\t\t\t\t\t\t\t<int key=\"NSMnemonicLoc\">2147483647</int>\n\t\t\t\t\t\t\t\t\t\t\t\t<reference key=\"NSOnImage\" ref=\"35465992\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t<reference key=\"NSMixedImage\" ref=\"502551668\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t<int key=\"NSTag\">1</int>\n\t\t\t\t\t\t\t\t\t\t\t</object>\n\t\t\t\t\t\t\t\t\t\t\t<object class=\"NSMenuItem\" id=\"330926929\">\n\t\t\t\t\t\t\t\t\t\t\t\t<reference key=\"NSMenu\" ref=\"786677654\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t<string key=\"NSTitle\">Underline</string>\n\t\t\t\t\t\t\t\t\t\t\t\t<string key=\"NSKeyEquiv\">u</string>\n\t\t\t\t\t\t\t\t\t\t\t\t<int key=\"NSKeyEquivModMask\">1048576</int>\n\t\t\t\t\t\t\t\t\t\t\t\t<int key=\"NSMnemonicLoc\">2147483647</int>\n\t\t\t\t\t\t\t\t\t\t\t\t<reference key=\"NSOnImage\" ref=\"35465992\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t<reference key=\"NSMixedImage\" ref=\"502551668\"/>\n\t\t\t\t\t\t\t\t\t\t\t</object>\n\t\t\t\t\t\t\t\t\t\t\t<object class=\"NSMenuItem\" id=\"533507878\">\n\t\t\t\t\t\t\t\t\t\t\t\t<reference key=\"NSMenu\" ref=\"786677654\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t<bool key=\"NSIsDisabled\">YES</bool>\n\t\t\t\t\t\t\t\t\t\t\t\t<bool key=\"NSIsSeparator\">YES</bool>\n\t\t\t\t\t\t\t\t\t\t\t\t<string key=\"NSTitle\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t<string key=\"NSKeyEquiv\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t<int key=\"NSMnemonicLoc\">2147483647</int>\n\t\t\t\t\t\t\t\t\t\t\t\t<reference key=\"NSOnImage\" ref=\"35465992\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t<reference key=\"NSMixedImage\" ref=\"502551668\"/>\n\t\t\t\t\t\t\t\t\t\t\t</object>\n\t\t\t\t\t\t\t\t\t\t\t<object class=\"NSMenuItem\" id=\"158063935\">\n\t\t\t\t\t\t\t\t\t\t\t\t<reference key=\"NSMenu\" ref=\"786677654\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t<string key=\"NSTitle\">Bigger</string>\n\t\t\t\t\t\t\t\t\t\t\t\t<string key=\"NSKeyEquiv\">+</string>\n\t\t\t\t\t\t\t\t\t\t\t\t<int key=\"NSKeyEquivModMask\">1048576</int>\n\t\t\t\t\t\t\t\t\t\t\t\t<int key=\"NSMnemonicLoc\">2147483647</int>\n\t\t\t\t\t\t\t\t\t\t\t\t<reference key=\"NSOnImage\" ref=\"35465992\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t<reference key=\"NSMixedImage\" ref=\"502551668\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t<int key=\"NSTag\">3</int>\n\t\t\t\t\t\t\t\t\t\t\t</object>\n\t\t\t\t\t\t\t\t\t\t\t<object class=\"NSMenuItem\" id=\"885547335\">\n\t\t\t\t\t\t\t\t\t\t\t\t<reference key=\"NSMenu\" ref=\"786677654\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t<string key=\"NSTitle\">Smaller</string>\n\t\t\t\t\t\t\t\t\t\t\t\t<string key=\"NSKeyEquiv\">-</string>\n\t\t\t\t\t\t\t\t\t\t\t\t<int key=\"NSKeyEquivModMask\">1048576</int>\n\t\t\t\t\t\t\t\t\t\t\t\t<int key=\"NSMnemonicLoc\">2147483647</int>\n\t\t\t\t\t\t\t\t\t\t\t\t<reference key=\"NSOnImage\" ref=\"35465992\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t<reference key=\"NSMixedImage\" ref=\"502551668\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t<int key=\"NSTag\">4</int>\n\t\t\t\t\t\t\t\t\t\t\t</object>\n\t\t\t\t\t\t\t\t\t\t\t<object class=\"NSMenuItem\" id=\"901062459\">\n\t\t\t\t\t\t\t\t\t\t\t\t<reference key=\"NSMenu\" ref=\"786677654\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t<bool key=\"NSIsDisabled\">YES</bool>\n\t\t\t\t\t\t\t\t\t\t\t\t<bool key=\"NSIsSeparator\">YES</bool>\n\t\t\t\t\t\t\t\t\t\t\t\t<string key=\"NSTitle\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t<string key=\"NSKeyEquiv\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t<int key=\"NSMnemonicLoc\">2147483647</int>\n\t\t\t\t\t\t\t\t\t\t\t\t<reference key=\"NSOnImage\" ref=\"35465992\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t<reference key=\"NSMixedImage\" ref=\"502551668\"/>\n\t\t\t\t\t\t\t\t\t\t\t</object>\n\t\t\t\t\t\t\t\t\t\t\t<object class=\"NSMenuItem\" id=\"767671776\">\n\t\t\t\t\t\t\t\t\t\t\t\t<reference key=\"NSMenu\" ref=\"786677654\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t<string key=\"NSTitle\">Kern</string>\n\t\t\t\t\t\t\t\t\t\t\t\t<string key=\"NSKeyEquiv\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t<int key=\"NSMnemonicLoc\">2147483647</int>\n\t\t\t\t\t\t\t\t\t\t\t\t<reference key=\"NSOnImage\" ref=\"35465992\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t<reference key=\"NSMixedImage\" ref=\"502551668\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t<string key=\"NSAction\">submenuAction:</string>\n\t\t\t\t\t\t\t\t\t\t\t\t<object class=\"NSMenu\" key=\"NSSubmenu\" id=\"175441468\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<string key=\"NSTitle\">Kern</string>\n\t\t\t\t\t\t\t\t\t\t\t\t\t<object class=\"NSMutableArray\" key=\"NSMenuItems\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<bool key=\"EncodedWithXMLCoder\">YES</bool>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<object class=\"NSMenuItem\" id=\"252969304\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<reference key=\"NSMenu\" ref=\"175441468\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<string key=\"NSTitle\">Use Default</string>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<string key=\"NSKeyEquiv\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<int key=\"NSMnemonicLoc\">2147483647</int>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<reference key=\"NSOnImage\" ref=\"35465992\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<reference key=\"NSMixedImage\" ref=\"502551668\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t</object>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<object class=\"NSMenuItem\" id=\"766922938\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<reference key=\"NSMenu\" ref=\"175441468\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<string key=\"NSTitle\">Use None</string>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<string key=\"NSKeyEquiv\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<int key=\"NSMnemonicLoc\">2147483647</int>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<reference key=\"NSOnImage\" ref=\"35465992\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<reference key=\"NSMixedImage\" ref=\"502551668\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t</object>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<object class=\"NSMenuItem\" id=\"677519740\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<reference key=\"NSMenu\" ref=\"175441468\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<string key=\"NSTitle\">Tighten</string>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<string key=\"NSKeyEquiv\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<int key=\"NSMnemonicLoc\">2147483647</int>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<reference key=\"NSOnImage\" ref=\"35465992\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<reference key=\"NSMixedImage\" ref=\"502551668\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t</object>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<object class=\"NSMenuItem\" id=\"238351151\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<reference key=\"NSMenu\" ref=\"175441468\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<string key=\"NSTitle\">Loosen</string>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<string key=\"NSKeyEquiv\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<int key=\"NSMnemonicLoc\">2147483647</int>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<reference key=\"NSOnImage\" ref=\"35465992\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<reference key=\"NSMixedImage\" ref=\"502551668\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t</object>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</object>\n\t\t\t\t\t\t\t\t\t\t\t\t</object>\n\t\t\t\t\t\t\t\t\t\t\t</object>\n\t\t\t\t\t\t\t\t\t\t\t<object class=\"NSMenuItem\" id=\"691570813\">\n\t\t\t\t\t\t\t\t\t\t\t\t<reference key=\"NSMenu\" ref=\"786677654\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t<string key=\"NSTitle\">Ligature</string>\n\t\t\t\t\t\t\t\t\t\t\t\t<string key=\"NSKeyEquiv\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t<int key=\"NSMnemonicLoc\">2147483647</int>\n\t\t\t\t\t\t\t\t\t\t\t\t<reference key=\"NSOnImage\" ref=\"35465992\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t<reference key=\"NSMixedImage\" ref=\"502551668\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t<string key=\"NSAction\">submenuAction:</string>\n\t\t\t\t\t\t\t\t\t\t\t\t<object class=\"NSMenu\" key=\"NSSubmenu\" id=\"1058217995\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<string key=\"NSTitle\">Ligature</string>\n\t\t\t\t\t\t\t\t\t\t\t\t\t<object class=\"NSMutableArray\" key=\"NSMenuItems\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<bool key=\"EncodedWithXMLCoder\">YES</bool>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<object class=\"NSMenuItem\" id=\"706297211\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<reference key=\"NSMenu\" ref=\"1058217995\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<string key=\"NSTitle\">Use Default</string>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<string key=\"NSKeyEquiv\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<int key=\"NSMnemonicLoc\">2147483647</int>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<reference key=\"NSOnImage\" ref=\"35465992\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<reference key=\"NSMixedImage\" ref=\"502551668\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t</object>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<object class=\"NSMenuItem\" id=\"568384683\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<reference key=\"NSMenu\" ref=\"1058217995\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<string key=\"NSTitle\">Use None</string>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<string key=\"NSKeyEquiv\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<int key=\"NSMnemonicLoc\">2147483647</int>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<reference key=\"NSOnImage\" ref=\"35465992\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<reference key=\"NSMixedImage\" ref=\"502551668\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t</object>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<object class=\"NSMenuItem\" id=\"663508465\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<reference key=\"NSMenu\" ref=\"1058217995\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<string key=\"NSTitle\">Use All</string>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<string key=\"NSKeyEquiv\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<int key=\"NSMnemonicLoc\">2147483647</int>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<reference key=\"NSOnImage\" ref=\"35465992\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<reference key=\"NSMixedImage\" ref=\"502551668\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t</object>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</object>\n\t\t\t\t\t\t\t\t\t\t\t\t</object>\n\t\t\t\t\t\t\t\t\t\t\t</object>\n\t\t\t\t\t\t\t\t\t\t\t<object class=\"NSMenuItem\" id=\"769124883\">\n\t\t\t\t\t\t\t\t\t\t\t\t<reference key=\"NSMenu\" ref=\"786677654\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t<string key=\"NSTitle\">Baseline</string>\n\t\t\t\t\t\t\t\t\t\t\t\t<string key=\"NSKeyEquiv\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t<int key=\"NSMnemonicLoc\">2147483647</int>\n\t\t\t\t\t\t\t\t\t\t\t\t<reference key=\"NSOnImage\" ref=\"35465992\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t<reference key=\"NSMixedImage\" ref=\"502551668\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t<string key=\"NSAction\">submenuAction:</string>\n\t\t\t\t\t\t\t\t\t\t\t\t<object class=\"NSMenu\" key=\"NSSubmenu\" id=\"18263474\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<string key=\"NSTitle\">Baseline</string>\n\t\t\t\t\t\t\t\t\t\t\t\t\t<object class=\"NSMutableArray\" key=\"NSMenuItems\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<bool key=\"EncodedWithXMLCoder\">YES</bool>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<object class=\"NSMenuItem\" id=\"257962622\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<reference key=\"NSMenu\" ref=\"18263474\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<string key=\"NSTitle\">Use Default</string>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<string key=\"NSKeyEquiv\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<int key=\"NSMnemonicLoc\">2147483647</int>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<reference key=\"NSOnImage\" ref=\"35465992\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<reference key=\"NSMixedImage\" ref=\"502551668\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t</object>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<object class=\"NSMenuItem\" id=\"644725453\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<reference key=\"NSMenu\" ref=\"18263474\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<string key=\"NSTitle\">Superscript</string>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<string key=\"NSKeyEquiv\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<int key=\"NSMnemonicLoc\">2147483647</int>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<reference key=\"NSOnImage\" ref=\"35465992\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<reference key=\"NSMixedImage\" ref=\"502551668\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t</object>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<object class=\"NSMenuItem\" id=\"1037576581\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<reference key=\"NSMenu\" ref=\"18263474\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<string key=\"NSTitle\">Subscript</string>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<string key=\"NSKeyEquiv\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<int key=\"NSMnemonicLoc\">2147483647</int>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<reference key=\"NSOnImage\" ref=\"35465992\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<reference key=\"NSMixedImage\" ref=\"502551668\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t</object>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<object class=\"NSMenuItem\" id=\"941806246\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<reference key=\"NSMenu\" ref=\"18263474\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<string key=\"NSTitle\">Raise</string>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<string key=\"NSKeyEquiv\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<int key=\"NSMnemonicLoc\">2147483647</int>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<reference key=\"NSOnImage\" ref=\"35465992\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<reference key=\"NSMixedImage\" ref=\"502551668\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t</object>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<object class=\"NSMenuItem\" id=\"1045724900\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<reference key=\"NSMenu\" ref=\"18263474\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<string key=\"NSTitle\">Lower</string>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<string key=\"NSKeyEquiv\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<int key=\"NSMnemonicLoc\">2147483647</int>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<reference key=\"NSOnImage\" ref=\"35465992\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<reference key=\"NSMixedImage\" ref=\"502551668\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t</object>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</object>\n\t\t\t\t\t\t\t\t\t\t\t\t</object>\n\t\t\t\t\t\t\t\t\t\t\t</object>\n\t\t\t\t\t\t\t\t\t\t\t<object class=\"NSMenuItem\" id=\"739652853\">\n\t\t\t\t\t\t\t\t\t\t\t\t<reference key=\"NSMenu\" ref=\"786677654\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t<bool key=\"NSIsDisabled\">YES</bool>\n\t\t\t\t\t\t\t\t\t\t\t\t<bool key=\"NSIsSeparator\">YES</bool>\n\t\t\t\t\t\t\t\t\t\t\t\t<string key=\"NSTitle\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t<string key=\"NSKeyEquiv\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t<int key=\"NSMnemonicLoc\">2147483647</int>\n\t\t\t\t\t\t\t\t\t\t\t\t<reference key=\"NSOnImage\" ref=\"35465992\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t<reference key=\"NSMixedImage\" ref=\"502551668\"/>\n\t\t\t\t\t\t\t\t\t\t\t</object>\n\t\t\t\t\t\t\t\t\t\t\t<object class=\"NSMenuItem\" id=\"1012600125\">\n\t\t\t\t\t\t\t\t\t\t\t\t<reference key=\"NSMenu\" ref=\"786677654\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t<string key=\"NSTitle\">Show Colors</string>\n\t\t\t\t\t\t\t\t\t\t\t\t<string key=\"NSKeyEquiv\">C</string>\n\t\t\t\t\t\t\t\t\t\t\t\t<int key=\"NSKeyEquivModMask\">1048576</int>\n\t\t\t\t\t\t\t\t\t\t\t\t<int key=\"NSMnemonicLoc\">2147483647</int>\n\t\t\t\t\t\t\t\t\t\t\t\t<reference key=\"NSOnImage\" ref=\"35465992\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t<reference key=\"NSMixedImage\" ref=\"502551668\"/>\n\t\t\t\t\t\t\t\t\t\t\t</object>\n\t\t\t\t\t\t\t\t\t\t\t<object class=\"NSMenuItem\" id=\"214559597\">\n\t\t\t\t\t\t\t\t\t\t\t\t<reference key=\"NSMenu\" ref=\"786677654\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t<bool key=\"NSIsDisabled\">YES</bool>\n\t\t\t\t\t\t\t\t\t\t\t\t<bool key=\"NSIsSeparator\">YES</bool>\n\t\t\t\t\t\t\t\t\t\t\t\t<string key=\"NSTitle\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t<string key=\"NSKeyEquiv\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t<int key=\"NSMnemonicLoc\">2147483647</int>\n\t\t\t\t\t\t\t\t\t\t\t\t<reference key=\"NSOnImage\" ref=\"35465992\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t<reference key=\"NSMixedImage\" ref=\"502551668\"/>\n\t\t\t\t\t\t\t\t\t\t\t</object>\n\t\t\t\t\t\t\t\t\t\t\t<object class=\"NSMenuItem\" id=\"596732606\">\n\t\t\t\t\t\t\t\t\t\t\t\t<reference key=\"NSMenu\" ref=\"786677654\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t<string key=\"NSTitle\">Copy Style</string>\n\t\t\t\t\t\t\t\t\t\t\t\t<string key=\"NSKeyEquiv\">c</string>\n\t\t\t\t\t\t\t\t\t\t\t\t<int key=\"NSKeyEquivModMask\">1572864</int>\n\t\t\t\t\t\t\t\t\t\t\t\t<int key=\"NSMnemonicLoc\">2147483647</int>\n\t\t\t\t\t\t\t\t\t\t\t\t<reference key=\"NSOnImage\" ref=\"35465992\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t<reference key=\"NSMixedImage\" ref=\"502551668\"/>\n\t\t\t\t\t\t\t\t\t\t\t</object>\n\t\t\t\t\t\t\t\t\t\t\t<object class=\"NSMenuItem\" id=\"393423671\">\n\t\t\t\t\t\t\t\t\t\t\t\t<reference key=\"NSMenu\" ref=\"786677654\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t<string key=\"NSTitle\">Paste Style</string>\n\t\t\t\t\t\t\t\t\t\t\t\t<string key=\"NSKeyEquiv\">v</string>\n\t\t\t\t\t\t\t\t\t\t\t\t<int key=\"NSKeyEquivModMask\">1572864</int>\n\t\t\t\t\t\t\t\t\t\t\t\t<int key=\"NSMnemonicLoc\">2147483647</int>\n\t\t\t\t\t\t\t\t\t\t\t\t<reference key=\"NSOnImage\" ref=\"35465992\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t<reference key=\"NSMixedImage\" ref=\"502551668\"/>\n\t\t\t\t\t\t\t\t\t\t\t</object>\n\t\t\t\t\t\t\t\t\t\t</object>\n\t\t\t\t\t\t\t\t\t\t<string key=\"NSName\">_NSFontMenu</string>\n\t\t\t\t\t\t\t\t\t</object>\n\t\t\t\t\t\t\t\t</object>\n\t\t\t\t\t\t\t\t<object class=\"NSMenuItem\" id=\"215659978\">\n\t\t\t\t\t\t\t\t\t<reference key=\"NSMenu\" ref=\"941447902\"/>\n\t\t\t\t\t\t\t\t\t<string key=\"NSTitle\">Text</string>\n\t\t\t\t\t\t\t\t\t<string key=\"NSKeyEquiv\"/>\n\t\t\t\t\t\t\t\t\t<int key=\"NSMnemonicLoc\">2147483647</int>\n\t\t\t\t\t\t\t\t\t<reference key=\"NSOnImage\" ref=\"35465992\"/>\n\t\t\t\t\t\t\t\t\t<reference key=\"NSMixedImage\" ref=\"502551668\"/>\n\t\t\t\t\t\t\t\t\t<string key=\"NSAction\">submenuAction:</string>\n\t\t\t\t\t\t\t\t\t<object class=\"NSMenu\" key=\"NSSubmenu\" id=\"446991534\">\n\t\t\t\t\t\t\t\t\t\t<string key=\"NSTitle\">Text</string>\n\t\t\t\t\t\t\t\t\t\t<object class=\"NSMutableArray\" key=\"NSMenuItems\">\n\t\t\t\t\t\t\t\t\t\t\t<bool key=\"EncodedWithXMLCoder\">YES</bool>\n\t\t\t\t\t\t\t\t\t\t\t<object class=\"NSMenuItem\" id=\"875092757\">\n\t\t\t\t\t\t\t\t\t\t\t\t<reference key=\"NSMenu\" ref=\"446991534\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t<string key=\"NSTitle\">Align Left</string>\n\t\t\t\t\t\t\t\t\t\t\t\t<string key=\"NSKeyEquiv\">{</string>\n\t\t\t\t\t\t\t\t\t\t\t\t<int key=\"NSKeyEquivModMask\">1048576</int>\n\t\t\t\t\t\t\t\t\t\t\t\t<int key=\"NSMnemonicLoc\">2147483647</int>\n\t\t\t\t\t\t\t\t\t\t\t\t<reference key=\"NSOnImage\" ref=\"35465992\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t<reference key=\"NSMixedImage\" ref=\"502551668\"/>\n\t\t\t\t\t\t\t\t\t\t\t</object>\n\t\t\t\t\t\t\t\t\t\t\t<object class=\"NSMenuItem\" id=\"630155264\">\n\t\t\t\t\t\t\t\t\t\t\t\t<reference key=\"NSMenu\" ref=\"446991534\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t<string key=\"NSTitle\">Center</string>\n\t\t\t\t\t\t\t\t\t\t\t\t<string key=\"NSKeyEquiv\">|</string>\n\t\t\t\t\t\t\t\t\t\t\t\t<int key=\"NSKeyEquivModMask\">1048576</int>\n\t\t\t\t\t\t\t\t\t\t\t\t<int key=\"NSMnemonicLoc\">2147483647</int>\n\t\t\t\t\t\t\t\t\t\t\t\t<reference key=\"NSOnImage\" ref=\"35465992\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t<reference key=\"NSMixedImage\" ref=\"502551668\"/>\n\t\t\t\t\t\t\t\t\t\t\t</object>\n\t\t\t\t\t\t\t\t\t\t\t<object class=\"NSMenuItem\" id=\"945678886\">\n\t\t\t\t\t\t\t\t\t\t\t\t<reference key=\"NSMenu\" ref=\"446991534\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t<string key=\"NSTitle\">Justify</string>\n\t\t\t\t\t\t\t\t\t\t\t\t<string key=\"NSKeyEquiv\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t<int key=\"NSMnemonicLoc\">2147483647</int>\n\t\t\t\t\t\t\t\t\t\t\t\t<reference key=\"NSOnImage\" ref=\"35465992\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t<reference key=\"NSMixedImage\" ref=\"502551668\"/>\n\t\t\t\t\t\t\t\t\t\t\t</object>\n\t\t\t\t\t\t\t\t\t\t\t<object class=\"NSMenuItem\" id=\"512868991\">\n\t\t\t\t\t\t\t\t\t\t\t\t<reference key=\"NSMenu\" ref=\"446991534\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t<string key=\"NSTitle\">Align Right</string>\n\t\t\t\t\t\t\t\t\t\t\t\t<string key=\"NSKeyEquiv\">}</string>\n\t\t\t\t\t\t\t\t\t\t\t\t<int key=\"NSKeyEquivModMask\">1048576</int>\n\t\t\t\t\t\t\t\t\t\t\t\t<int key=\"NSMnemonicLoc\">2147483647</int>\n\t\t\t\t\t\t\t\t\t\t\t\t<reference key=\"NSOnImage\" ref=\"35465992\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t<reference key=\"NSMixedImage\" ref=\"502551668\"/>\n\t\t\t\t\t\t\t\t\t\t\t</object>\n\t\t\t\t\t\t\t\t\t\t\t<object class=\"NSMenuItem\" id=\"163117631\">\n\t\t\t\t\t\t\t\t\t\t\t\t<reference key=\"NSMenu\" ref=\"446991534\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t<bool key=\"NSIsDisabled\">YES</bool>\n\t\t\t\t\t\t\t\t\t\t\t\t<bool key=\"NSIsSeparator\">YES</bool>\n\t\t\t\t\t\t\t\t\t\t\t\t<string key=\"NSTitle\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t<string key=\"NSKeyEquiv\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t<int key=\"NSMnemonicLoc\">2147483647</int>\n\t\t\t\t\t\t\t\t\t\t\t\t<reference key=\"NSOnImage\" ref=\"35465992\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t<reference key=\"NSMixedImage\" ref=\"502551668\"/>\n\t\t\t\t\t\t\t\t\t\t\t</object>\n\t\t\t\t\t\t\t\t\t\t\t<object class=\"NSMenuItem\" id=\"31516759\">\n\t\t\t\t\t\t\t\t\t\t\t\t<reference key=\"NSMenu\" ref=\"446991534\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t<string key=\"NSTitle\">Writing Direction</string>\n\t\t\t\t\t\t\t\t\t\t\t\t<string key=\"NSKeyEquiv\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t<int key=\"NSMnemonicLoc\">2147483647</int>\n\t\t\t\t\t\t\t\t\t\t\t\t<reference key=\"NSOnImage\" ref=\"35465992\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t<reference key=\"NSMixedImage\" ref=\"502551668\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t<string key=\"NSAction\">submenuAction:</string>\n\t\t\t\t\t\t\t\t\t\t\t\t<object class=\"NSMenu\" key=\"NSSubmenu\" id=\"956096989\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<string key=\"NSTitle\">Writing Direction</string>\n\t\t\t\t\t\t\t\t\t\t\t\t\t<object class=\"NSMutableArray\" key=\"NSMenuItems\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<bool key=\"EncodedWithXMLCoder\">YES</bool>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<object class=\"NSMenuItem\" id=\"257099033\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<reference key=\"NSMenu\" ref=\"956096989\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<bool key=\"NSIsDisabled\">YES</bool>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<string key=\"NSTitle\">Paragraph</string>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<string key=\"NSKeyEquiv\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<int key=\"NSMnemonicLoc\">2147483647</int>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<reference key=\"NSOnImage\" ref=\"35465992\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<reference key=\"NSMixedImage\" ref=\"502551668\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t</object>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<object class=\"NSMenuItem\" id=\"551969625\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<reference key=\"NSMenu\" ref=\"956096989\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<string type=\"base64-UTF8\" key=\"NSTitle\">CURlZmF1bHQ</string>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<string key=\"NSKeyEquiv\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<int key=\"NSMnemonicLoc\">2147483647</int>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<reference key=\"NSOnImage\" ref=\"35465992\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<reference key=\"NSMixedImage\" ref=\"502551668\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t</object>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<object class=\"NSMenuItem\" id=\"249532473\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<reference key=\"NSMenu\" ref=\"956096989\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<string type=\"base64-UTF8\" key=\"NSTitle\">CUxlZnQgdG8gUmlnaHQ</string>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<string key=\"NSKeyEquiv\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<int key=\"NSMnemonicLoc\">2147483647</int>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<reference key=\"NSOnImage\" ref=\"35465992\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<reference key=\"NSMixedImage\" ref=\"502551668\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t</object>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<object class=\"NSMenuItem\" id=\"607364498\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<reference key=\"NSMenu\" ref=\"956096989\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<string type=\"base64-UTF8\" key=\"NSTitle\">CVJpZ2h0IHRvIExlZnQ</string>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<string key=\"NSKeyEquiv\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<int key=\"NSMnemonicLoc\">2147483647</int>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<reference key=\"NSOnImage\" ref=\"35465992\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<reference key=\"NSMixedImage\" ref=\"502551668\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t</object>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<object class=\"NSMenuItem\" id=\"508151438\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<reference key=\"NSMenu\" ref=\"956096989\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<bool key=\"NSIsDisabled\">YES</bool>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<bool key=\"NSIsSeparator\">YES</bool>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<string key=\"NSTitle\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<string key=\"NSKeyEquiv\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<int key=\"NSMnemonicLoc\">2147483647</int>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<reference key=\"NSOnImage\" ref=\"35465992\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<reference key=\"NSMixedImage\" ref=\"502551668\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t</object>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<object class=\"NSMenuItem\" id=\"981751889\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<reference key=\"NSMenu\" ref=\"956096989\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<bool key=\"NSIsDisabled\">YES</bool>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<string key=\"NSTitle\">Selection</string>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<string key=\"NSKeyEquiv\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<int key=\"NSMnemonicLoc\">2147483647</int>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<reference key=\"NSOnImage\" ref=\"35465992\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<reference key=\"NSMixedImage\" ref=\"502551668\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t</object>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<object class=\"NSMenuItem\" id=\"380031999\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<reference key=\"NSMenu\" ref=\"956096989\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<string type=\"base64-UTF8\" key=\"NSTitle\">CURlZmF1bHQ</string>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<string key=\"NSKeyEquiv\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<int key=\"NSMnemonicLoc\">2147483647</int>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<reference key=\"NSOnImage\" ref=\"35465992\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<reference key=\"NSMixedImage\" ref=\"502551668\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t</object>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<object class=\"NSMenuItem\" id=\"825984362\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<reference key=\"NSMenu\" ref=\"956096989\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<string type=\"base64-UTF8\" key=\"NSTitle\">CUxlZnQgdG8gUmlnaHQ</string>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<string key=\"NSKeyEquiv\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<int key=\"NSMnemonicLoc\">2147483647</int>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<reference key=\"NSOnImage\" ref=\"35465992\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<reference key=\"NSMixedImage\" ref=\"502551668\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t</object>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<object class=\"NSMenuItem\" id=\"560145579\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<reference key=\"NSMenu\" ref=\"956096989\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<string type=\"base64-UTF8\" key=\"NSTitle\">CVJpZ2h0IHRvIExlZnQ</string>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<string key=\"NSKeyEquiv\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<int key=\"NSMnemonicLoc\">2147483647</int>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<reference key=\"NSOnImage\" ref=\"35465992\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<reference key=\"NSMixedImage\" ref=\"502551668\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t</object>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</object>\n\t\t\t\t\t\t\t\t\t\t\t\t</object>\n\t\t\t\t\t\t\t\t\t\t\t</object>\n\t\t\t\t\t\t\t\t\t\t\t<object class=\"NSMenuItem\" id=\"908105787\">\n\t\t\t\t\t\t\t\t\t\t\t\t<reference key=\"NSMenu\" ref=\"446991534\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t<bool key=\"NSIsDisabled\">YES</bool>\n\t\t\t\t\t\t\t\t\t\t\t\t<bool key=\"NSIsSeparator\">YES</bool>\n\t\t\t\t\t\t\t\t\t\t\t\t<string key=\"NSTitle\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t<string key=\"NSKeyEquiv\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t<int key=\"NSMnemonicLoc\">2147483647</int>\n\t\t\t\t\t\t\t\t\t\t\t\t<reference key=\"NSOnImage\" ref=\"35465992\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t<reference key=\"NSMixedImage\" ref=\"502551668\"/>\n\t\t\t\t\t\t\t\t\t\t\t</object>\n\t\t\t\t\t\t\t\t\t\t\t<object class=\"NSMenuItem\" id=\"644046920\">\n\t\t\t\t\t\t\t\t\t\t\t\t<reference key=\"NSMenu\" ref=\"446991534\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t<string key=\"NSTitle\">Show Ruler</string>\n\t\t\t\t\t\t\t\t\t\t\t\t<string key=\"NSKeyEquiv\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t<int key=\"NSMnemonicLoc\">2147483647</int>\n\t\t\t\t\t\t\t\t\t\t\t\t<reference key=\"NSOnImage\" ref=\"35465992\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t<reference key=\"NSMixedImage\" ref=\"502551668\"/>\n\t\t\t\t\t\t\t\t\t\t\t</object>\n\t\t\t\t\t\t\t\t\t\t\t<object class=\"NSMenuItem\" id=\"231811626\">\n\t\t\t\t\t\t\t\t\t\t\t\t<reference key=\"NSMenu\" ref=\"446991534\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t<string key=\"NSTitle\">Copy Ruler</string>\n\t\t\t\t\t\t\t\t\t\t\t\t<string key=\"NSKeyEquiv\">c</string>\n\t\t\t\t\t\t\t\t\t\t\t\t<int key=\"NSKeyEquivModMask\">1310720</int>\n\t\t\t\t\t\t\t\t\t\t\t\t<int key=\"NSMnemonicLoc\">2147483647</int>\n\t\t\t\t\t\t\t\t\t\t\t\t<reference key=\"NSOnImage\" ref=\"35465992\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t<reference key=\"NSMixedImage\" ref=\"502551668\"/>\n\t\t\t\t\t\t\t\t\t\t\t</object>\n\t\t\t\t\t\t\t\t\t\t\t<object class=\"NSMenuItem\" id=\"883618387\">\n\t\t\t\t\t\t\t\t\t\t\t\t<reference key=\"NSMenu\" ref=\"446991534\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t<string key=\"NSTitle\">Paste Ruler</string>\n\t\t\t\t\t\t\t\t\t\t\t\t<string key=\"NSKeyEquiv\">v</string>\n\t\t\t\t\t\t\t\t\t\t\t\t<int key=\"NSKeyEquivModMask\">1310720</int>\n\t\t\t\t\t\t\t\t\t\t\t\t<int key=\"NSMnemonicLoc\">2147483647</int>\n\t\t\t\t\t\t\t\t\t\t\t\t<reference key=\"NSOnImage\" ref=\"35465992\"/>\n\t\t\t\t\t\t\t\t\t\t\t\t<reference key=\"NSMixedImage\" ref=\"502551668\"/>\n\t\t\t\t\t\t\t\t\t\t\t</object>\n\t\t\t\t\t\t\t\t\t\t</object>\n\t\t\t\t\t\t\t\t\t</object>\n\t\t\t\t\t\t\t\t</object>\n\t\t\t\t\t\t\t</object>\n\t\t\t\t\t\t</object>\n\t\t\t\t\t</object>\n\t\t\t\t\t<object class=\"NSMenuItem\" id=\"586577488\">\n\t\t\t\t\t\t<reference key=\"NSMenu\" ref=\"649796088\"/>\n\t\t\t\t\t\t<string key=\"NSTitle\">View</string>\n\t\t\t\t\t\t<string key=\"NSKeyEquiv\"/>\n\t\t\t\t\t\t<int key=\"NSKeyEquivModMask\">1048576</int>\n\t\t\t\t\t\t<int key=\"NSMnemonicLoc\">2147483647</int>\n\t\t\t\t\t\t<reference key=\"NSOnImage\" ref=\"35465992\"/>\n\t\t\t\t\t\t<reference key=\"NSMixedImage\" ref=\"502551668\"/>\n\t\t\t\t\t\t<string key=\"NSAction\">submenuAction:</string>\n\t\t\t\t\t\t<object class=\"NSMenu\" key=\"NSSubmenu\" id=\"466310130\">\n\t\t\t\t\t\t\t<string key=\"NSTitle\">View</string>\n\t\t\t\t\t\t\t<object class=\"NSMutableArray\" key=\"NSMenuItems\">\n\t\t\t\t\t\t\t\t<bool key=\"EncodedWithXMLCoder\">YES</bool>\n\t\t\t\t\t\t\t\t<object class=\"NSMenuItem\" id=\"102151532\">\n\t\t\t\t\t\t\t\t\t<reference key=\"NSMenu\" ref=\"466310130\"/>\n\t\t\t\t\t\t\t\t\t<string key=\"NSTitle\">Show Toolbar</string>\n\t\t\t\t\t\t\t\t\t<string key=\"NSKeyEquiv\">t</string>\n\t\t\t\t\t\t\t\t\t<int key=\"NSKeyEquivModMask\">1572864</int>\n\t\t\t\t\t\t\t\t\t<int key=\"NSMnemonicLoc\">2147483647</int>\n\t\t\t\t\t\t\t\t\t<reference key=\"NSOnImage\" ref=\"35465992\"/>\n\t\t\t\t\t\t\t\t\t<reference key=\"NSMixedImage\" ref=\"502551668\"/>\n\t\t\t\t\t\t\t\t</object>\n\t\t\t\t\t\t\t\t<object class=\"NSMenuItem\" id=\"237841660\">\n\t\t\t\t\t\t\t\t\t<reference key=\"NSMenu\" ref=\"466310130\"/>\n\t\t\t\t\t\t\t\t\t<string key=\"NSTitle\">Customize Toolbar…</string>\n\t\t\t\t\t\t\t\t\t<string key=\"NSKeyEquiv\"/>\n\t\t\t\t\t\t\t\t\t<int key=\"NSKeyEquivModMask\">1048576</int>\n\t\t\t\t\t\t\t\t\t<int key=\"NSMnemonicLoc\">2147483647</int>\n\t\t\t\t\t\t\t\t\t<reference key=\"NSOnImage\" ref=\"35465992\"/>\n\t\t\t\t\t\t\t\t\t<reference key=\"NSMixedImage\" ref=\"502551668\"/>\n\t\t\t\t\t\t\t\t</object>\n\t\t\t\t\t\t\t</object>\n\t\t\t\t\t\t</object>\n\t\t\t\t\t</object>\n\t\t\t\t\t<object class=\"NSMenuItem\" id=\"713487014\">\n\t\t\t\t\t\t<reference key=\"NSMenu\" ref=\"649796088\"/>\n\t\t\t\t\t\t<string key=\"NSTitle\">Window</string>\n\t\t\t\t\t\t<string key=\"NSKeyEquiv\"/>\n\t\t\t\t\t\t<int key=\"NSKeyEquivModMask\">1048576</int>\n\t\t\t\t\t\t<int key=\"NSMnemonicLoc\">2147483647</int>\n\t\t\t\t\t\t<reference key=\"NSOnImage\" ref=\"35465992\"/>\n\t\t\t\t\t\t<reference key=\"NSMixedImage\" ref=\"502551668\"/>\n\t\t\t\t\t\t<string key=\"NSAction\">submenuAction:</string>\n\t\t\t\t\t\t<object class=\"NSMenu\" key=\"NSSubmenu\" id=\"835318025\">\n\t\t\t\t\t\t\t<string key=\"NSTitle\">Window</string>\n\t\t\t\t\t\t\t<object class=\"NSMutableArray\" key=\"NSMenuItems\">\n\t\t\t\t\t\t\t\t<bool key=\"EncodedWithXMLCoder\">YES</bool>\n\t\t\t\t\t\t\t\t<object class=\"NSMenuItem\" id=\"1011231497\">\n\t\t\t\t\t\t\t\t\t<reference key=\"NSMenu\" ref=\"835318025\"/>\n\t\t\t\t\t\t\t\t\t<string key=\"NSTitle\">Minimize</string>\n\t\t\t\t\t\t\t\t\t<string key=\"NSKeyEquiv\">m</string>\n\t\t\t\t\t\t\t\t\t<int key=\"NSKeyEquivModMask\">1048576</int>\n\t\t\t\t\t\t\t\t\t<int key=\"NSMnemonicLoc\">2147483647</int>\n\t\t\t\t\t\t\t\t\t<reference key=\"NSOnImage\" ref=\"35465992\"/>\n\t\t\t\t\t\t\t\t\t<reference key=\"NSMixedImage\" ref=\"502551668\"/>\n\t\t\t\t\t\t\t\t</object>\n\t\t\t\t\t\t\t\t<object class=\"NSMenuItem\" id=\"575023229\">\n\t\t\t\t\t\t\t\t\t<reference key=\"NSMenu\" ref=\"835318025\"/>\n\t\t\t\t\t\t\t\t\t<string key=\"NSTitle\">Zoom</string>\n\t\t\t\t\t\t\t\t\t<string key=\"NSKeyEquiv\"/>\n\t\t\t\t\t\t\t\t\t<int key=\"NSKeyEquivModMask\">1048576</int>\n\t\t\t\t\t\t\t\t\t<int key=\"NSMnemonicLoc\">2147483647</int>\n\t\t\t\t\t\t\t\t\t<reference key=\"NSOnImage\" ref=\"35465992\"/>\n\t\t\t\t\t\t\t\t\t<reference key=\"NSMixedImage\" ref=\"502551668\"/>\n\t\t\t\t\t\t\t\t</object>\n\t\t\t\t\t\t\t\t<object class=\"NSMenuItem\" id=\"299356726\">\n\t\t\t\t\t\t\t\t\t<reference key=\"NSMenu\" ref=\"835318025\"/>\n\t\t\t\t\t\t\t\t\t<bool key=\"NSIsDisabled\">YES</bool>\n\t\t\t\t\t\t\t\t\t<bool key=\"NSIsSeparator\">YES</bool>\n\t\t\t\t\t\t\t\t\t<string key=\"NSTitle\"/>\n\t\t\t\t\t\t\t\t\t<string key=\"NSKeyEquiv\"/>\n\t\t\t\t\t\t\t\t\t<int key=\"NSKeyEquivModMask\">1048576</int>\n\t\t\t\t\t\t\t\t\t<int key=\"NSMnemonicLoc\">2147483647</int>\n\t\t\t\t\t\t\t\t\t<reference key=\"NSOnImage\" ref=\"35465992\"/>\n\t\t\t\t\t\t\t\t\t<reference key=\"NSMixedImage\" ref=\"502551668\"/>\n\t\t\t\t\t\t\t\t</object>\n\t\t\t\t\t\t\t\t<object class=\"NSMenuItem\" id=\"625202149\">\n\t\t\t\t\t\t\t\t\t<reference key=\"NSMenu\" ref=\"835318025\"/>\n\t\t\t\t\t\t\t\t\t<string key=\"NSTitle\">Bring All to Front</string>\n\t\t\t\t\t\t\t\t\t<string key=\"NSKeyEquiv\"/>\n\t\t\t\t\t\t\t\t\t<int key=\"NSKeyEquivModMask\">1048576</int>\n\t\t\t\t\t\t\t\t\t<int key=\"NSMnemonicLoc\">2147483647</int>\n\t\t\t\t\t\t\t\t\t<reference key=\"NSOnImage\" ref=\"35465992\"/>\n\t\t\t\t\t\t\t\t\t<reference key=\"NSMixedImage\" ref=\"502551668\"/>\n\t\t\t\t\t\t\t\t</object>\n\t\t\t\t\t\t\t</object>\n\t\t\t\t\t\t\t<string key=\"NSName\">_NSWindowsMenu</string>\n\t\t\t\t\t\t</object>\n\t\t\t\t\t</object>\n\t\t\t\t\t<object class=\"NSMenuItem\" id=\"448692316\">\n\t\t\t\t\t\t<reference key=\"NSMenu\" ref=\"649796088\"/>\n\t\t\t\t\t\t<string key=\"NSTitle\">Help</string>\n\t\t\t\t\t\t<string key=\"NSKeyEquiv\"/>\n\t\t\t\t\t\t<int key=\"NSMnemonicLoc\">2147483647</int>\n\t\t\t\t\t\t<reference key=\"NSOnImage\" ref=\"35465992\"/>\n\t\t\t\t\t\t<reference key=\"NSMixedImage\" ref=\"502551668\"/>\n\t\t\t\t\t\t<string key=\"NSAction\">submenuAction:</string>\n\t\t\t\t\t\t<object class=\"NSMenu\" key=\"NSSubmenu\" id=\"992780483\">\n\t\t\t\t\t\t\t<string key=\"NSTitle\">Help</string>\n\t\t\t\t\t\t\t<object class=\"NSMutableArray\" key=\"NSMenuItems\">\n\t\t\t\t\t\t\t\t<bool key=\"EncodedWithXMLCoder\">YES</bool>\n\t\t\t\t\t\t\t\t<object class=\"NSMenuItem\" id=\"105068016\">\n\t\t\t\t\t\t\t\t\t<reference key=\"NSMenu\" ref=\"992780483\"/>\n\t\t\t\t\t\t\t\t\t<string key=\"NSTitle\">Randomify Help</string>\n\t\t\t\t\t\t\t\t\t<string key=\"NSKeyEquiv\">?</string>\n\t\t\t\t\t\t\t\t\t<int key=\"NSKeyEquivModMask\">1048576</int>\n\t\t\t\t\t\t\t\t\t<int key=\"NSMnemonicLoc\">2147483647</int>\n\t\t\t\t\t\t\t\t\t<reference key=\"NSOnImage\" ref=\"35465992\"/>\n\t\t\t\t\t\t\t\t\t<reference key=\"NSMixedImage\" ref=\"502551668\"/>\n\t\t\t\t\t\t\t\t</object>\n\t\t\t\t\t\t\t</object>\n\t\t\t\t\t\t\t<string key=\"NSName\">_NSHelpMenu</string>\n\t\t\t\t\t\t</object>\n\t\t\t\t\t</object>\n\t\t\t\t</object>\n\t\t\t\t<string key=\"NSName\">_NSMainMenu</string>\n\t\t\t</object>\n\t\t\t<object class=\"NSWindowTemplate\" id=\"972006081\">\n\t\t\t\t<int key=\"NSWindowStyleMask\">15</int>\n\t\t\t\t<int key=\"NSWindowBacking\">2</int>\n\t\t\t\t<string key=\"NSWindowRect\">{{335, 428}, {497, 322}}</string>\n\t\t\t\t<int key=\"NSWTFlags\">1954021376</int>\n\t\t\t\t<string key=\"NSWindowTitle\">Randomify</string>\n\t\t\t\t<string key=\"NSWindowClass\">NSWindow</string>\n\t\t\t\t<nil key=\"NSViewClass\"/>\n\t\t\t\t<string key=\"NSWindowContentMaxSize\">{1.79769e+308, 1.79769e+308}</string>\n\t\t\t\t<object class=\"NSView\" key=\"NSWindowView\" id=\"439893737\">\n\t\t\t\t\t<reference key=\"NSNextResponder\"/>\n\t\t\t\t\t<int key=\"NSvFlags\">256</int>\n\t\t\t\t\t<object class=\"NSMutableArray\" key=\"NSSubviews\">\n\t\t\t\t\t\t<bool key=\"EncodedWithXMLCoder\">YES</bool>\n\t\t\t\t\t\t<object class=\"NSTextField\" id=\"765794976\">\n\t\t\t\t\t\t\t<reference key=\"NSNextResponder\" ref=\"439893737\"/>\n\t\t\t\t\t\t\t<int key=\"NSvFlags\">292</int>\n\t\t\t\t\t\t\t<string key=\"NSFrame\">{{20, 20}, {158, 22}}</string>\n\t\t\t\t\t\t\t<reference key=\"NSSuperview\" ref=\"439893737\"/>\n\t\t\t\t\t\t\t<bool key=\"NSEnabled\">YES</bool>\n\t\t\t\t\t\t\t<object class=\"NSTextFieldCell\" key=\"NSCell\" id=\"579012641\">\n\t\t\t\t\t\t\t\t<int key=\"NSCellFlags\">-1804468671</int>\n\t\t\t\t\t\t\t\t<int key=\"NSCellFlags2\">272630784</int>\n\t\t\t\t\t\t\t\t<string key=\"NSContents\"/>\n\t\t\t\t\t\t\t\t<object class=\"NSFont\" key=\"NSSupport\" id=\"667493830\">\n\t\t\t\t\t\t\t\t\t<string key=\"NSName\">LucidaGrande</string>\n\t\t\t\t\t\t\t\t\t<double key=\"NSSize\">13</double>\n\t\t\t\t\t\t\t\t\t<int key=\"NSfFlags\">1044</int>\n\t\t\t\t\t\t\t\t</object>\n\t\t\t\t\t\t\t\t<string key=\"NSPlaceholderString\">Username</string>\n\t\t\t\t\t\t\t\t<reference key=\"NSControlView\" ref=\"765794976\"/>\n\t\t\t\t\t\t\t\t<bool key=\"NSDrawsBackground\">YES</bool>\n\t\t\t\t\t\t\t\t<object class=\"NSColor\" key=\"NSBackgroundColor\" id=\"869802087\">\n\t\t\t\t\t\t\t\t\t<int key=\"NSColorSpace\">6</int>\n\t\t\t\t\t\t\t\t\t<string key=\"NSCatalogName\">System</string>\n\t\t\t\t\t\t\t\t\t<string key=\"NSColorName\">textBackgroundColor</string>\n\t\t\t\t\t\t\t\t\t<object class=\"NSColor\" key=\"NSColor\">\n\t\t\t\t\t\t\t\t\t\t<int key=\"NSColorSpace\">3</int>\n\t\t\t\t\t\t\t\t\t\t<bytes key=\"NSWhite\">MQA</bytes>\n\t\t\t\t\t\t\t\t\t</object>\n\t\t\t\t\t\t\t\t</object>\n\t\t\t\t\t\t\t\t<object class=\"NSColor\" key=\"NSTextColor\" id=\"327752861\">\n\t\t\t\t\t\t\t\t\t<int key=\"NSColorSpace\">6</int>\n\t\t\t\t\t\t\t\t\t<string key=\"NSCatalogName\">System</string>\n\t\t\t\t\t\t\t\t\t<string key=\"NSColorName\">textColor</string>\n\t\t\t\t\t\t\t\t\t<object class=\"NSColor\" key=\"NSColor\" id=\"1009300105\">\n\t\t\t\t\t\t\t\t\t\t<int key=\"NSColorSpace\">3</int>\n\t\t\t\t\t\t\t\t\t\t<bytes key=\"NSWhite\">MAA</bytes>\n\t\t\t\t\t\t\t\t\t</object>\n\t\t\t\t\t\t\t\t</object>\n\t\t\t\t\t\t\t</object>\n\t\t\t\t\t\t</object>\n\t\t\t\t\t\t<object class=\"NSSecureTextField\" id=\"394479719\">\n\t\t\t\t\t\t\t<reference key=\"NSNextResponder\" ref=\"439893737\"/>\n\t\t\t\t\t\t\t<int key=\"NSvFlags\">288</int>\n\t\t\t\t\t\t\t<string key=\"NSFrame\">{{182, 20}, {158, 22}}</string>\n\t\t\t\t\t\t\t<reference key=\"NSSuperview\" ref=\"439893737\"/>\n\t\t\t\t\t\t\t<bool key=\"NSEnabled\">YES</bool>\n\t\t\t\t\t\t\t<object class=\"NSSecureTextFieldCell\" key=\"NSCell\" id=\"16471822\">\n\t\t\t\t\t\t\t\t<int key=\"NSCellFlags\">343014976</int>\n\t\t\t\t\t\t\t\t<int key=\"NSCellFlags2\">272630784</int>\n\t\t\t\t\t\t\t\t<string key=\"NSContents\"/>\n\t\t\t\t\t\t\t\t<reference key=\"NSSupport\" ref=\"667493830\"/>\n\t\t\t\t\t\t\t\t<string key=\"NSPlaceholderString\">Password</string>\n\t\t\t\t\t\t\t\t<reference key=\"NSControlView\" ref=\"394479719\"/>\n\t\t\t\t\t\t\t\t<bool key=\"NSDrawsBackground\">YES</bool>\n\t\t\t\t\t\t\t\t<reference key=\"NSBackgroundColor\" ref=\"869802087\"/>\n\t\t\t\t\t\t\t\t<reference key=\"NSTextColor\" ref=\"327752861\"/>\n\t\t\t\t\t\t\t\t<object class=\"NSArray\" key=\"NSAllowedInputLocales\">\n\t\t\t\t\t\t\t\t\t<bool key=\"EncodedWithXMLCoder\">YES</bool>\n\t\t\t\t\t\t\t\t\t<string>NSAllRomanInputSourcesLocaleIdentifier</string>\n\t\t\t\t\t\t\t\t</object>\n\t\t\t\t\t\t\t</object>\n\t\t\t\t\t\t</object>\n\t\t\t\t\t\t<object class=\"NSButton\" id=\"327821739\">\n\t\t\t\t\t\t\t<reference key=\"NSNextResponder\" ref=\"439893737\"/>\n\t\t\t\t\t\t\t<int key=\"NSvFlags\">297</int>\n\t\t\t\t\t\t\t<string key=\"NSFrame\">{{366, 13}, {117, 32}}</string>\n\t\t\t\t\t\t\t<reference key=\"NSSuperview\" ref=\"439893737\"/>\n\t\t\t\t\t\t\t<bool key=\"NSEnabled\">YES</bool>\n\t\t\t\t\t\t\t<object class=\"NSButtonCell\" key=\"NSCell\" id=\"122895619\">\n\t\t\t\t\t\t\t\t<int key=\"NSCellFlags\">67239424</int>\n\t\t\t\t\t\t\t\t<int key=\"NSCellFlags2\">134217728</int>\n\t\t\t\t\t\t\t\t<string key=\"NSContents\">Login &amp; Play</string>\n\t\t\t\t\t\t\t\t<reference key=\"NSSupport\" ref=\"667493830\"/>\n\t\t\t\t\t\t\t\t<reference key=\"NSControlView\" ref=\"327821739\"/>\n\t\t\t\t\t\t\t\t<int key=\"NSButtonFlags\">-2038284033</int>\n\t\t\t\t\t\t\t\t<int key=\"NSButtonFlags2\">129</int>\n\t\t\t\t\t\t\t\t<string key=\"NSAlternateContents\"/>\n\t\t\t\t\t\t\t\t<string type=\"base64-UTF8\" key=\"NSKeyEquivalent\">DQ</string>\n\t\t\t\t\t\t\t\t<int key=\"NSPeriodicDelay\">200</int>\n\t\t\t\t\t\t\t\t<int key=\"NSPeriodicInterval\">25</int>\n\t\t\t\t\t\t\t</object>\n\t\t\t\t\t\t</object>\n\t\t\t\t\t\t<object class=\"NSTextField\" id=\"167731747\">\n\t\t\t\t\t\t\t<reference key=\"NSNextResponder\" ref=\"439893737\"/>\n\t\t\t\t\t\t\t<int key=\"NSvFlags\">274</int>\n\t\t\t\t\t\t\t<string key=\"NSFrame\">{{20, 66}, {457, 216}}</string>\n\t\t\t\t\t\t\t<reference key=\"NSSuperview\" ref=\"439893737\"/>\n\t\t\t\t\t\t\t<bool key=\"NSEnabled\">YES</bool>\n\t\t\t\t\t\t\t<object class=\"NSTextFieldCell\" key=\"NSCell\" id=\"855023043\">\n\t\t\t\t\t\t\t\t<int key=\"NSCellFlags\">-2073952767</int>\n\t\t\t\t\t\t\t\t<int key=\"NSCellFlags2\">272629760</int>\n\t\t\t\t\t\t\t\t<string key=\"NSContents\"/>\n\t\t\t\t\t\t\t\t<reference key=\"NSSupport\" ref=\"667493830\"/>\n\t\t\t\t\t\t\t\t<reference key=\"NSControlView\" ref=\"167731747\"/>\n\t\t\t\t\t\t\t\t<bool key=\"NSDrawsBackground\">YES</bool>\n\t\t\t\t\t\t\t\t<reference key=\"NSBackgroundColor\" ref=\"869802087\"/>\n\t\t\t\t\t\t\t\t<reference key=\"NSTextColor\" ref=\"327752861\"/>\n\t\t\t\t\t\t\t</object>\n\t\t\t\t\t\t</object>\n\t\t\t\t\t\t<object class=\"NSButton\" id=\"935404353\">\n\t\t\t\t\t\t\t<reference key=\"NSNextResponder\" ref=\"439893737\"/>\n\t\t\t\t\t\t\t<int key=\"NSvFlags\">265</int>\n\t\t\t\t\t\t\t<string key=\"NSFrame\">{{372, 289}, {48, 26}}</string>\n\t\t\t\t\t\t\t<reference key=\"NSSuperview\" ref=\"439893737\"/>\n\t\t\t\t\t\t\t<bool key=\"NSEnabled\">YES</bool>\n\t\t\t\t\t\t\t<object class=\"NSButtonCell\" key=\"NSCell\" id=\"785091278\">\n\t\t\t\t\t\t\t\t<int key=\"NSCellFlags\">-2080244224</int>\n\t\t\t\t\t\t\t\t<int key=\"NSCellFlags2\">134217728</int>\n\t\t\t\t\t\t\t\t<string key=\"NSContents\">║</string>\n\t\t\t\t\t\t\t\t<object class=\"NSFont\" key=\"NSSupport\">\n\t\t\t\t\t\t\t\t\t<string key=\"NSName\">STHeitiSC-Light</string>\n\t\t\t\t\t\t\t\t\t<double key=\"NSSize\">12</double>\n\t\t\t\t\t\t\t\t\t<int key=\"NSfFlags\">16</int>\n\t\t\t\t\t\t\t\t</object>\n\t\t\t\t\t\t\t\t<reference key=\"NSControlView\" ref=\"935404353\"/>\n\t\t\t\t\t\t\t\t<int key=\"NSButtonFlags\">-2033434369</int>\n\t\t\t\t\t\t\t\t<int key=\"NSButtonFlags2\">162</int>\n\t\t\t\t\t\t\t\t<string key=\"NSAlternateContents\"/>\n\t\t\t\t\t\t\t\t<string key=\"NSKeyEquivalent\"/>\n\t\t\t\t\t\t\t\t<int key=\"NSPeriodicDelay\">400</int>\n\t\t\t\t\t\t\t\t<int key=\"NSPeriodicInterval\">75</int>\n\t\t\t\t\t\t\t</object>\n\t\t\t\t\t\t</object>\n\t\t\t\t\t\t<object class=\"NSButton\" id=\"264769268\">\n\t\t\t\t\t\t\t<reference key=\"NSNextResponder\" ref=\"439893737\"/>\n\t\t\t\t\t\t\t<int key=\"NSvFlags\">265</int>\n\t\t\t\t\t\t\t<string key=\"NSFrame\">{{429, 290}, {48, 25}}</string>\n\t\t\t\t\t\t\t<reference key=\"NSSuperview\" ref=\"439893737\"/>\n\t\t\t\t\t\t\t<bool key=\"NSEnabled\">YES</bool>\n\t\t\t\t\t\t\t<object class=\"NSButtonCell\" key=\"NSCell\" id=\"516108178\">\n\t\t\t\t\t\t\t\t<int key=\"NSCellFlags\">-2080244224</int>\n\t\t\t\t\t\t\t\t<int key=\"NSCellFlags2\">134217728</int>\n\t\t\t\t\t\t\t\t<string key=\"NSContents\">⇒</string>\n\t\t\t\t\t\t\t\t<object class=\"NSFont\" key=\"NSSupport\">\n\t\t\t\t\t\t\t\t\t<string key=\"NSName\">HiraKakuProN-W3</string>\n\t\t\t\t\t\t\t\t\t<double key=\"NSSize\">32</double>\n\t\t\t\t\t\t\t\t\t<int key=\"NSfFlags\">16</int>\n\t\t\t\t\t\t\t\t</object>\n\t\t\t\t\t\t\t\t<reference key=\"NSControlView\" ref=\"264769268\"/>\n\t\t\t\t\t\t\t\t<int key=\"NSButtonFlags\">-2033434369</int>\n\t\t\t\t\t\t\t\t<int key=\"NSButtonFlags2\">162</int>\n\t\t\t\t\t\t\t\t<string key=\"NSAlternateContents\"/>\n\t\t\t\t\t\t\t\t<string key=\"NSKeyEquivalent\"/>\n\t\t\t\t\t\t\t\t<int key=\"NSPeriodicDelay\">400</int>\n\t\t\t\t\t\t\t\t<int key=\"NSPeriodicInterval\">75</int>\n\t\t\t\t\t\t\t</object>\n\t\t\t\t\t\t</object>\n\t\t\t\t\t\t<object class=\"NSTextField\" id=\"663855000\">\n\t\t\t\t\t\t\t<reference key=\"NSNextResponder\" ref=\"439893737\"/>\n\t\t\t\t\t\t\t<int key=\"NSvFlags\">292</int>\n\t\t\t\t\t\t\t<string key=\"NSFrame\">{{17, 44}, {164, 14}}</string>\n\t\t\t\t\t\t\t<reference key=\"NSSuperview\" ref=\"439893737\"/>\n\t\t\t\t\t\t\t<bool key=\"NSEnabled\">YES</bool>\n\t\t\t\t\t\t\t<object class=\"NSTextFieldCell\" key=\"NSCell\" id=\"400581401\">\n\t\t\t\t\t\t\t\t<int key=\"NSCellFlags\">68288064</int>\n\t\t\t\t\t\t\t\t<int key=\"NSCellFlags2\">272761856</int>\n\t\t\t\t\t\t\t\t<string key=\"NSContents\">Username</string>\n\t\t\t\t\t\t\t\t<object class=\"NSFont\" key=\"NSSupport\" id=\"26\">\n\t\t\t\t\t\t\t\t\t<string key=\"NSName\">LucidaGrande</string>\n\t\t\t\t\t\t\t\t\t<double key=\"NSSize\">11</double>\n\t\t\t\t\t\t\t\t\t<int key=\"NSfFlags\">3100</int>\n\t\t\t\t\t\t\t\t</object>\n\t\t\t\t\t\t\t\t<reference key=\"NSControlView\" ref=\"663855000\"/>\n\t\t\t\t\t\t\t\t<object class=\"NSColor\" key=\"NSBackgroundColor\" id=\"113529340\">\n\t\t\t\t\t\t\t\t\t<int key=\"NSColorSpace\">6</int>\n\t\t\t\t\t\t\t\t\t<string key=\"NSCatalogName\">System</string>\n\t\t\t\t\t\t\t\t\t<string key=\"NSColorName\">controlColor</string>\n\t\t\t\t\t\t\t\t\t<object class=\"NSColor\" key=\"NSColor\">\n\t\t\t\t\t\t\t\t\t\t<int key=\"NSColorSpace\">3</int>\n\t\t\t\t\t\t\t\t\t\t<bytes key=\"NSWhite\">MC42NjY2NjY2NjY3AA</bytes>\n\t\t\t\t\t\t\t\t\t</object>\n\t\t\t\t\t\t\t\t</object>\n\t\t\t\t\t\t\t\t<object class=\"NSColor\" key=\"NSTextColor\" id=\"769338032\">\n\t\t\t\t\t\t\t\t\t<int key=\"NSColorSpace\">6</int>\n\t\t\t\t\t\t\t\t\t<string key=\"NSCatalogName\">System</string>\n\t\t\t\t\t\t\t\t\t<string key=\"NSColorName\">controlTextColor</string>\n\t\t\t\t\t\t\t\t\t<reference key=\"NSColor\" ref=\"1009300105\"/>\n\t\t\t\t\t\t\t\t</object>\n\t\t\t\t\t\t\t</object>\n\t\t\t\t\t\t</object>\n\t\t\t\t\t\t<object class=\"NSTextField\" id=\"783923701\">\n\t\t\t\t\t\t\t<reference key=\"NSNextResponder\" ref=\"439893737\"/>\n\t\t\t\t\t\t\t<int key=\"NSvFlags\">292</int>\n\t\t\t\t\t\t\t<string key=\"NSFrame\">{{179, 44}, {164, 14}}</string>\n\t\t\t\t\t\t\t<reference key=\"NSSuperview\" ref=\"439893737\"/>\n\t\t\t\t\t\t\t<bool key=\"NSEnabled\">YES</bool>\n\t\t\t\t\t\t\t<object class=\"NSTextFieldCell\" key=\"NSCell\" id=\"78164212\">\n\t\t\t\t\t\t\t\t<int key=\"NSCellFlags\">68288064</int>\n\t\t\t\t\t\t\t\t<int key=\"NSCellFlags2\">272761856</int>\n\t\t\t\t\t\t\t\t<string key=\"NSContents\">Password</string>\n\t\t\t\t\t\t\t\t<reference key=\"NSSupport\" ref=\"26\"/>\n\t\t\t\t\t\t\t\t<reference key=\"NSControlView\" ref=\"783923701\"/>\n\t\t\t\t\t\t\t\t<reference key=\"NSBackgroundColor\" ref=\"113529340\"/>\n\t\t\t\t\t\t\t\t<reference key=\"NSTextColor\" ref=\"769338032\"/>\n\t\t\t\t\t\t\t</object>\n\t\t\t\t\t\t</object>\n\t\t\t\t\t\t<object class=\"NSTextField\" id=\"161503078\">\n\t\t\t\t\t\t\t<reference key=\"NSNextResponder\" ref=\"439893737\"/>\n\t\t\t\t\t\t\t<int key=\"NSvFlags\">266</int>\n\t\t\t\t\t\t\t<string key=\"NSFrame\">{{17, 291}, {340, 18}}</string>\n\t\t\t\t\t\t\t<reference key=\"NSSuperview\" ref=\"439893737\"/>\n\t\t\t\t\t\t\t<bool key=\"NSEnabled\">YES</bool>\n\t\t\t\t\t\t\t<object class=\"NSTextFieldCell\" key=\"NSCell\" id=\"1040653779\">\n\t\t\t\t\t\t\t\t<int key=\"NSCellFlags\">67239488</int>\n\t\t\t\t\t\t\t\t<int key=\"NSCellFlags2\">272631808</int>\n\t\t\t\t\t\t\t\t<string key=\"NSContents\">Playing x by y</string>\n\t\t\t\t\t\t\t\t<object class=\"NSFont\" key=\"NSSupport\">\n\t\t\t\t\t\t\t\t\t<string key=\"NSName\">LucidaGrande-Bold</string>\n\t\t\t\t\t\t\t\t\t<double key=\"NSSize\">14</double>\n\t\t\t\t\t\t\t\t\t<int key=\"NSfFlags\">16</int>\n\t\t\t\t\t\t\t\t</object>\n\t\t\t\t\t\t\t\t<reference key=\"NSControlView\" ref=\"161503078\"/>\n\t\t\t\t\t\t\t\t<reference key=\"NSBackgroundColor\" ref=\"113529340\"/>\n\t\t\t\t\t\t\t\t<reference key=\"NSTextColor\" ref=\"769338032\"/>\n\t\t\t\t\t\t\t</object>\n\t\t\t\t\t\t</object>\n\t\t\t\t\t</object>\n\t\t\t\t\t<string key=\"NSFrameSize\">{497, 322}</string>\n\t\t\t\t\t<reference key=\"NSSuperview\"/>\n\t\t\t\t</object>\n\t\t\t\t<string key=\"NSScreenRect\">{{0, 0}, {1920, 1178}}</string>\n\t\t\t\t<string key=\"NSMaxSize\">{1.79769e+308, 1.79769e+308}</string>\n\t\t\t</object>\n\t\t\t<object class=\"NSCustomObject\" id=\"976324537\">\n\t\t\t\t<string key=\"NSClassName\">RandomifyAppDelegate</string>\n\t\t\t</object>\n\t\t\t<object class=\"NSCustomObject\" id=\"755631768\">\n\t\t\t\t<string key=\"NSClassName\">NSFontManager</string>\n\t\t\t</object>\n\t\t\t<object class=\"NSUserDefaultsController\" id=\"1007787480\">\n\t\t\t\t<object class=\"NSMutableArray\" key=\"NSDeclaredKeys\">\n\t\t\t\t\t<bool key=\"EncodedWithXMLCoder\">YES</bool>\n\t\t\t\t\t<string>username</string>\n\t\t\t\t\t<string>password</string>\n\t\t\t\t</object>\n\t\t\t\t<bool key=\"NSSharedInstance\">YES</bool>\n\t\t\t</object>\n\t\t</object>\n\t\t<object class=\"IBObjectContainer\" key=\"IBDocument.Objects\">\n\t\t\t<object class=\"NSMutableArray\" key=\"connectionRecords\">\n\t\t\t\t<bool key=\"EncodedWithXMLCoder\">YES</bool>\n\t\t\t\t<object class=\"IBConnectionRecord\">\n\t\t\t\t\t<object class=\"IBActionConnection\" key=\"connection\">\n\t\t\t\t\t\t<string key=\"label\">performMiniaturize:</string>\n\t\t\t\t\t\t<reference key=\"source\" ref=\"1014\"/>\n\t\t\t\t\t\t<reference key=\"destination\" ref=\"1011231497\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<int key=\"connectionID\">37</int>\n\t\t\t\t</object>\n\t\t\t\t<object class=\"IBConnectionRecord\">\n\t\t\t\t\t<object class=\"IBActionConnection\" key=\"connection\">\n\t\t\t\t\t\t<string key=\"label\">arrangeInFront:</string>\n\t\t\t\t\t\t<reference key=\"source\" ref=\"1014\"/>\n\t\t\t\t\t\t<reference key=\"destination\" ref=\"625202149\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<int key=\"connectionID\">39</int>\n\t\t\t\t</object>\n\t\t\t\t<object class=\"IBConnectionRecord\">\n\t\t\t\t\t<object class=\"IBActionConnection\" key=\"connection\">\n\t\t\t\t\t\t<string key=\"label\">print:</string>\n\t\t\t\t\t\t<reference key=\"source\" ref=\"1014\"/>\n\t\t\t\t\t\t<reference key=\"destination\" ref=\"49223823\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<int key=\"connectionID\">86</int>\n\t\t\t\t</object>\n\t\t\t\t<object class=\"IBConnectionRecord\">\n\t\t\t\t\t<object class=\"IBActionConnection\" key=\"connection\">\n\t\t\t\t\t\t<string key=\"label\">runPageLayout:</string>\n\t\t\t\t\t\t<reference key=\"source\" ref=\"1014\"/>\n\t\t\t\t\t\t<reference key=\"destination\" ref=\"294629803\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<int key=\"connectionID\">87</int>\n\t\t\t\t</object>\n\t\t\t\t<object class=\"IBConnectionRecord\">\n\t\t\t\t\t<object class=\"IBActionConnection\" key=\"connection\">\n\t\t\t\t\t\t<string key=\"label\">clearRecentDocuments:</string>\n\t\t\t\t\t\t<reference key=\"source\" ref=\"1014\"/>\n\t\t\t\t\t\t<reference key=\"destination\" ref=\"759406840\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<int key=\"connectionID\">127</int>\n\t\t\t\t</object>\n\t\t\t\t<object class=\"IBConnectionRecord\">\n\t\t\t\t\t<object class=\"IBActionConnection\" key=\"connection\">\n\t\t\t\t\t\t<string key=\"label\">orderFrontStandardAboutPanel:</string>\n\t\t\t\t\t\t<reference key=\"source\" ref=\"1021\"/>\n\t\t\t\t\t\t<reference key=\"destination\" ref=\"238522557\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<int key=\"connectionID\">142</int>\n\t\t\t\t</object>\n\t\t\t\t<object class=\"IBConnectionRecord\">\n\t\t\t\t\t<object class=\"IBActionConnection\" key=\"connection\">\n\t\t\t\t\t\t<string key=\"label\">performClose:</string>\n\t\t\t\t\t\t<reference key=\"source\" ref=\"1014\"/>\n\t\t\t\t\t\t<reference key=\"destination\" ref=\"776162233\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<int key=\"connectionID\">193</int>\n\t\t\t\t</object>\n\t\t\t\t<object class=\"IBConnectionRecord\">\n\t\t\t\t\t<object class=\"IBActionConnection\" key=\"connection\">\n\t\t\t\t\t\t<string key=\"label\">toggleContinuousSpellChecking:</string>\n\t\t\t\t\t\t<reference key=\"source\" ref=\"1014\"/>\n\t\t\t\t\t\t<reference key=\"destination\" ref=\"948374510\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<int key=\"connectionID\">222</int>\n\t\t\t\t</object>\n\t\t\t\t<object class=\"IBConnectionRecord\">\n\t\t\t\t\t<object class=\"IBActionConnection\" key=\"connection\">\n\t\t\t\t\t\t<string key=\"label\">undo:</string>\n\t\t\t\t\t\t<reference key=\"source\" ref=\"1014\"/>\n\t\t\t\t\t\t<reference key=\"destination\" ref=\"1058277027\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<int key=\"connectionID\">223</int>\n\t\t\t\t</object>\n\t\t\t\t<object class=\"IBConnectionRecord\">\n\t\t\t\t\t<object class=\"IBActionConnection\" key=\"connection\">\n\t\t\t\t\t\t<string key=\"label\">copy:</string>\n\t\t\t\t\t\t<reference key=\"source\" ref=\"1014\"/>\n\t\t\t\t\t\t<reference key=\"destination\" ref=\"860595796\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<int key=\"connectionID\">224</int>\n\t\t\t\t</object>\n\t\t\t\t<object class=\"IBConnectionRecord\">\n\t\t\t\t\t<object class=\"IBActionConnection\" key=\"connection\">\n\t\t\t\t\t\t<string key=\"label\">checkSpelling:</string>\n\t\t\t\t\t\t<reference key=\"source\" ref=\"1014\"/>\n\t\t\t\t\t\t<reference key=\"destination\" ref=\"96193923\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<int key=\"connectionID\">225</int>\n\t\t\t\t</object>\n\t\t\t\t<object class=\"IBConnectionRecord\">\n\t\t\t\t\t<object class=\"IBActionConnection\" key=\"connection\">\n\t\t\t\t\t\t<string key=\"label\">paste:</string>\n\t\t\t\t\t\t<reference key=\"source\" ref=\"1014\"/>\n\t\t\t\t\t\t<reference key=\"destination\" ref=\"29853731\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<int key=\"connectionID\">226</int>\n\t\t\t\t</object>\n\t\t\t\t<object class=\"IBConnectionRecord\">\n\t\t\t\t\t<object class=\"IBActionConnection\" key=\"connection\">\n\t\t\t\t\t\t<string key=\"label\">stopSpeaking:</string>\n\t\t\t\t\t\t<reference key=\"source\" ref=\"1014\"/>\n\t\t\t\t\t\t<reference key=\"destination\" ref=\"680220178\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<int key=\"connectionID\">227</int>\n\t\t\t\t</object>\n\t\t\t\t<object class=\"IBConnectionRecord\">\n\t\t\t\t\t<object class=\"IBActionConnection\" key=\"connection\">\n\t\t\t\t\t\t<string key=\"label\">cut:</string>\n\t\t\t\t\t\t<reference key=\"source\" ref=\"1014\"/>\n\t\t\t\t\t\t<reference key=\"destination\" ref=\"296257095\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<int key=\"connectionID\">228</int>\n\t\t\t\t</object>\n\t\t\t\t<object class=\"IBConnectionRecord\">\n\t\t\t\t\t<object class=\"IBActionConnection\" key=\"connection\">\n\t\t\t\t\t\t<string key=\"label\">showGuessPanel:</string>\n\t\t\t\t\t\t<reference key=\"source\" ref=\"1014\"/>\n\t\t\t\t\t\t<reference key=\"destination\" ref=\"679648819\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<int key=\"connectionID\">230</int>\n\t\t\t\t</object>\n\t\t\t\t<object class=\"IBConnectionRecord\">\n\t\t\t\t\t<object class=\"IBActionConnection\" key=\"connection\">\n\t\t\t\t\t\t<string key=\"label\">redo:</string>\n\t\t\t\t\t\t<reference key=\"source\" ref=\"1014\"/>\n\t\t\t\t\t\t<reference key=\"destination\" ref=\"790794224\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<int key=\"connectionID\">231</int>\n\t\t\t\t</object>\n\t\t\t\t<object class=\"IBConnectionRecord\">\n\t\t\t\t\t<object class=\"IBActionConnection\" key=\"connection\">\n\t\t\t\t\t\t<string key=\"label\">selectAll:</string>\n\t\t\t\t\t\t<reference key=\"source\" ref=\"1014\"/>\n\t\t\t\t\t\t<reference key=\"destination\" ref=\"583158037\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<int key=\"connectionID\">232</int>\n\t\t\t\t</object>\n\t\t\t\t<object class=\"IBConnectionRecord\">\n\t\t\t\t\t<object class=\"IBActionConnection\" key=\"connection\">\n\t\t\t\t\t\t<string key=\"label\">startSpeaking:</string>\n\t\t\t\t\t\t<reference key=\"source\" ref=\"1014\"/>\n\t\t\t\t\t\t<reference key=\"destination\" ref=\"731782645\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<int key=\"connectionID\">233</int>\n\t\t\t\t</object>\n\t\t\t\t<object class=\"IBConnectionRecord\">\n\t\t\t\t\t<object class=\"IBActionConnection\" key=\"connection\">\n\t\t\t\t\t\t<string key=\"label\">delete:</string>\n\t\t\t\t\t\t<reference key=\"source\" ref=\"1014\"/>\n\t\t\t\t\t\t<reference key=\"destination\" ref=\"437104165\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<int key=\"connectionID\">235</int>\n\t\t\t\t</object>\n\t\t\t\t<object class=\"IBConnectionRecord\">\n\t\t\t\t\t<object class=\"IBActionConnection\" key=\"connection\">\n\t\t\t\t\t\t<string key=\"label\">performZoom:</string>\n\t\t\t\t\t\t<reference key=\"source\" ref=\"1014\"/>\n\t\t\t\t\t\t<reference key=\"destination\" ref=\"575023229\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<int key=\"connectionID\">240</int>\n\t\t\t\t</object>\n\t\t\t\t<object class=\"IBConnectionRecord\">\n\t\t\t\t\t<object class=\"IBActionConnection\" key=\"connection\">\n\t\t\t\t\t\t<string key=\"label\">performFindPanelAction:</string>\n\t\t\t\t\t\t<reference key=\"source\" ref=\"1014\"/>\n\t\t\t\t\t\t<reference key=\"destination\" ref=\"447796847\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<int key=\"connectionID\">241</int>\n\t\t\t\t</object>\n\t\t\t\t<object class=\"IBConnectionRecord\">\n\t\t\t\t\t<object class=\"IBActionConnection\" key=\"connection\">\n\t\t\t\t\t\t<string key=\"label\">centerSelectionInVisibleArea:</string>\n\t\t\t\t\t\t<reference key=\"source\" ref=\"1014\"/>\n\t\t\t\t\t\t<reference key=\"destination\" ref=\"88285865\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<int key=\"connectionID\">245</int>\n\t\t\t\t</object>\n\t\t\t\t<object class=\"IBConnectionRecord\">\n\t\t\t\t\t<object class=\"IBActionConnection\" key=\"connection\">\n\t\t\t\t\t\t<string key=\"label\">toggleGrammarChecking:</string>\n\t\t\t\t\t\t<reference key=\"source\" ref=\"1014\"/>\n\t\t\t\t\t\t<reference key=\"destination\" ref=\"967646866\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<int key=\"connectionID\">347</int>\n\t\t\t\t</object>\n\t\t\t\t<object class=\"IBConnectionRecord\">\n\t\t\t\t\t<object class=\"IBActionConnection\" key=\"connection\">\n\t\t\t\t\t\t<string key=\"label\">toggleSmartInsertDelete:</string>\n\t\t\t\t\t\t<reference key=\"source\" ref=\"1014\"/>\n\t\t\t\t\t\t<reference key=\"destination\" ref=\"605118523\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<int key=\"connectionID\">355</int>\n\t\t\t\t</object>\n\t\t\t\t<object class=\"IBConnectionRecord\">\n\t\t\t\t\t<object class=\"IBActionConnection\" key=\"connection\">\n\t\t\t\t\t\t<string key=\"label\">toggleAutomaticQuoteSubstitution:</string>\n\t\t\t\t\t\t<reference key=\"source\" ref=\"1014\"/>\n\t\t\t\t\t\t<reference key=\"destination\" ref=\"197661976\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<int key=\"connectionID\">356</int>\n\t\t\t\t</object>\n\t\t\t\t<object class=\"IBConnectionRecord\">\n\t\t\t\t\t<object class=\"IBActionConnection\" key=\"connection\">\n\t\t\t\t\t\t<string key=\"label\">toggleAutomaticLinkDetection:</string>\n\t\t\t\t\t\t<reference key=\"source\" ref=\"1014\"/>\n\t\t\t\t\t\t<reference key=\"destination\" ref=\"708854459\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<int key=\"connectionID\">357</int>\n\t\t\t\t</object>\n\t\t\t\t<object class=\"IBConnectionRecord\">\n\t\t\t\t\t<object class=\"IBActionConnection\" key=\"connection\">\n\t\t\t\t\t\t<string key=\"label\">saveDocument:</string>\n\t\t\t\t\t\t<reference key=\"source\" ref=\"1014\"/>\n\t\t\t\t\t\t<reference key=\"destination\" ref=\"1023925487\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<int key=\"connectionID\">362</int>\n\t\t\t\t</object>\n\t\t\t\t<object class=\"IBConnectionRecord\">\n\t\t\t\t\t<object class=\"IBActionConnection\" key=\"connection\">\n\t\t\t\t\t\t<string key=\"label\">saveDocumentAs:</string>\n\t\t\t\t\t\t<reference key=\"source\" ref=\"1014\"/>\n\t\t\t\t\t\t<reference key=\"destination\" ref=\"117038363\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<int key=\"connectionID\">363</int>\n\t\t\t\t</object>\n\t\t\t\t<object class=\"IBConnectionRecord\">\n\t\t\t\t\t<object class=\"IBActionConnection\" key=\"connection\">\n\t\t\t\t\t\t<string key=\"label\">revertDocumentToSaved:</string>\n\t\t\t\t\t\t<reference key=\"source\" ref=\"1014\"/>\n\t\t\t\t\t\t<reference key=\"destination\" ref=\"579971712\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<int key=\"connectionID\">364</int>\n\t\t\t\t</object>\n\t\t\t\t<object class=\"IBConnectionRecord\">\n\t\t\t\t\t<object class=\"IBActionConnection\" key=\"connection\">\n\t\t\t\t\t\t<string key=\"label\">runToolbarCustomizationPalette:</string>\n\t\t\t\t\t\t<reference key=\"source\" ref=\"1014\"/>\n\t\t\t\t\t\t<reference key=\"destination\" ref=\"237841660\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<int key=\"connectionID\">365</int>\n\t\t\t\t</object>\n\t\t\t\t<object class=\"IBConnectionRecord\">\n\t\t\t\t\t<object class=\"IBActionConnection\" key=\"connection\">\n\t\t\t\t\t\t<string key=\"label\">toggleToolbarShown:</string>\n\t\t\t\t\t\t<reference key=\"source\" ref=\"1014\"/>\n\t\t\t\t\t\t<reference key=\"destination\" ref=\"102151532\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<int key=\"connectionID\">366</int>\n\t\t\t\t</object>\n\t\t\t\t<object class=\"IBConnectionRecord\">\n\t\t\t\t\t<object class=\"IBActionConnection\" key=\"connection\">\n\t\t\t\t\t\t<string key=\"label\">hide:</string>\n\t\t\t\t\t\t<reference key=\"source\" ref=\"1014\"/>\n\t\t\t\t\t\t<reference key=\"destination\" ref=\"755159360\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<int key=\"connectionID\">367</int>\n\t\t\t\t</object>\n\t\t\t\t<object class=\"IBConnectionRecord\">\n\t\t\t\t\t<object class=\"IBActionConnection\" key=\"connection\">\n\t\t\t\t\t\t<string key=\"label\">hideOtherApplications:</string>\n\t\t\t\t\t\t<reference key=\"source\" ref=\"1014\"/>\n\t\t\t\t\t\t<reference key=\"destination\" ref=\"342932134\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<int key=\"connectionID\">368</int>\n\t\t\t\t</object>\n\t\t\t\t<object class=\"IBConnectionRecord\">\n\t\t\t\t\t<object class=\"IBActionConnection\" key=\"connection\">\n\t\t\t\t\t\t<string key=\"label\">unhideAllApplications:</string>\n\t\t\t\t\t\t<reference key=\"source\" ref=\"1014\"/>\n\t\t\t\t\t\t<reference key=\"destination\" ref=\"908899353\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<int key=\"connectionID\">370</int>\n\t\t\t\t</object>\n\t\t\t\t<object class=\"IBConnectionRecord\">\n\t\t\t\t\t<object class=\"IBActionConnection\" key=\"connection\">\n\t\t\t\t\t\t<string key=\"label\">newDocument:</string>\n\t\t\t\t\t\t<reference key=\"source\" ref=\"1014\"/>\n\t\t\t\t\t\t<reference key=\"destination\" ref=\"705341025\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<int key=\"connectionID\">373</int>\n\t\t\t\t</object>\n\t\t\t\t<object class=\"IBConnectionRecord\">\n\t\t\t\t\t<object class=\"IBActionConnection\" key=\"connection\">\n\t\t\t\t\t\t<string key=\"label\">openDocument:</string>\n\t\t\t\t\t\t<reference key=\"source\" ref=\"1014\"/>\n\t\t\t\t\t\t<reference key=\"destination\" ref=\"722745758\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<int key=\"connectionID\">374</int>\n\t\t\t\t</object>\n\t\t\t\t<object class=\"IBConnectionRecord\">\n\t\t\t\t\t<object class=\"IBActionConnection\" key=\"connection\">\n\t\t\t\t\t\t<string key=\"label\">addFontTrait:</string>\n\t\t\t\t\t\t<reference key=\"source\" ref=\"755631768\"/>\n\t\t\t\t\t\t<reference key=\"destination\" ref=\"305399458\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<int key=\"connectionID\">421</int>\n\t\t\t\t</object>\n\t\t\t\t<object class=\"IBConnectionRecord\">\n\t\t\t\t\t<object class=\"IBActionConnection\" key=\"connection\">\n\t\t\t\t\t\t<string key=\"label\">addFontTrait:</string>\n\t\t\t\t\t\t<reference key=\"source\" ref=\"755631768\"/>\n\t\t\t\t\t\t<reference key=\"destination\" ref=\"814362025\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<int key=\"connectionID\">422</int>\n\t\t\t\t</object>\n\t\t\t\t<object class=\"IBConnectionRecord\">\n\t\t\t\t\t<object class=\"IBActionConnection\" key=\"connection\">\n\t\t\t\t\t\t<string key=\"label\">modifyFont:</string>\n\t\t\t\t\t\t<reference key=\"source\" ref=\"755631768\"/>\n\t\t\t\t\t\t<reference key=\"destination\" ref=\"885547335\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<int key=\"connectionID\">423</int>\n\t\t\t\t</object>\n\t\t\t\t<object class=\"IBConnectionRecord\">\n\t\t\t\t\t<object class=\"IBActionConnection\" key=\"connection\">\n\t\t\t\t\t\t<string key=\"label\">orderFrontFontPanel:</string>\n\t\t\t\t\t\t<reference key=\"source\" ref=\"755631768\"/>\n\t\t\t\t\t\t<reference key=\"destination\" ref=\"159677712\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<int key=\"connectionID\">424</int>\n\t\t\t\t</object>\n\t\t\t\t<object class=\"IBConnectionRecord\">\n\t\t\t\t\t<object class=\"IBActionConnection\" key=\"connection\">\n\t\t\t\t\t\t<string key=\"label\">modifyFont:</string>\n\t\t\t\t\t\t<reference key=\"source\" ref=\"755631768\"/>\n\t\t\t\t\t\t<reference key=\"destination\" ref=\"158063935\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<int key=\"connectionID\">425</int>\n\t\t\t\t</object>\n\t\t\t\t<object class=\"IBConnectionRecord\">\n\t\t\t\t\t<object class=\"IBActionConnection\" key=\"connection\">\n\t\t\t\t\t\t<string key=\"label\">raiseBaseline:</string>\n\t\t\t\t\t\t<reference key=\"source\" ref=\"1014\"/>\n\t\t\t\t\t\t<reference key=\"destination\" ref=\"941806246\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<int key=\"connectionID\">426</int>\n\t\t\t\t</object>\n\t\t\t\t<object class=\"IBConnectionRecord\">\n\t\t\t\t\t<object class=\"IBActionConnection\" key=\"connection\">\n\t\t\t\t\t\t<string key=\"label\">lowerBaseline:</string>\n\t\t\t\t\t\t<reference key=\"source\" ref=\"1014\"/>\n\t\t\t\t\t\t<reference key=\"destination\" ref=\"1045724900\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<int key=\"connectionID\">427</int>\n\t\t\t\t</object>\n\t\t\t\t<object class=\"IBConnectionRecord\">\n\t\t\t\t\t<object class=\"IBActionConnection\" key=\"connection\">\n\t\t\t\t\t\t<string key=\"label\">copyFont:</string>\n\t\t\t\t\t\t<reference key=\"source\" ref=\"1014\"/>\n\t\t\t\t\t\t<reference key=\"destination\" ref=\"596732606\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<int key=\"connectionID\">428</int>\n\t\t\t\t</object>\n\t\t\t\t<object class=\"IBConnectionRecord\">\n\t\t\t\t\t<object class=\"IBActionConnection\" key=\"connection\">\n\t\t\t\t\t\t<string key=\"label\">subscript:</string>\n\t\t\t\t\t\t<reference key=\"source\" ref=\"1014\"/>\n\t\t\t\t\t\t<reference key=\"destination\" ref=\"1037576581\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<int key=\"connectionID\">429</int>\n\t\t\t\t</object>\n\t\t\t\t<object class=\"IBConnectionRecord\">\n\t\t\t\t\t<object class=\"IBActionConnection\" key=\"connection\">\n\t\t\t\t\t\t<string key=\"label\">superscript:</string>\n\t\t\t\t\t\t<reference key=\"source\" ref=\"1014\"/>\n\t\t\t\t\t\t<reference key=\"destination\" ref=\"644725453\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<int key=\"connectionID\">430</int>\n\t\t\t\t</object>\n\t\t\t\t<object class=\"IBConnectionRecord\">\n\t\t\t\t\t<object class=\"IBActionConnection\" key=\"connection\">\n\t\t\t\t\t\t<string key=\"label\">tightenKerning:</string>\n\t\t\t\t\t\t<reference key=\"source\" ref=\"1014\"/>\n\t\t\t\t\t\t<reference key=\"destination\" ref=\"677519740\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<int key=\"connectionID\">431</int>\n\t\t\t\t</object>\n\t\t\t\t<object class=\"IBConnectionRecord\">\n\t\t\t\t\t<object class=\"IBActionConnection\" key=\"connection\">\n\t\t\t\t\t\t<string key=\"label\">underline:</string>\n\t\t\t\t\t\t<reference key=\"source\" ref=\"1014\"/>\n\t\t\t\t\t\t<reference key=\"destination\" ref=\"330926929\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<int key=\"connectionID\">432</int>\n\t\t\t\t</object>\n\t\t\t\t<object class=\"IBConnectionRecord\">\n\t\t\t\t\t<object class=\"IBActionConnection\" key=\"connection\">\n\t\t\t\t\t\t<string key=\"label\">orderFrontColorPanel:</string>\n\t\t\t\t\t\t<reference key=\"source\" ref=\"1014\"/>\n\t\t\t\t\t\t<reference key=\"destination\" ref=\"1012600125\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<int key=\"connectionID\">433</int>\n\t\t\t\t</object>\n\t\t\t\t<object class=\"IBConnectionRecord\">\n\t\t\t\t\t<object class=\"IBActionConnection\" key=\"connection\">\n\t\t\t\t\t\t<string key=\"label\">useAllLigatures:</string>\n\t\t\t\t\t\t<reference key=\"source\" ref=\"1014\"/>\n\t\t\t\t\t\t<reference key=\"destination\" ref=\"663508465\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<int key=\"connectionID\">434</int>\n\t\t\t\t</object>\n\t\t\t\t<object class=\"IBConnectionRecord\">\n\t\t\t\t\t<object class=\"IBActionConnection\" key=\"connection\">\n\t\t\t\t\t\t<string key=\"label\">loosenKerning:</string>\n\t\t\t\t\t\t<reference key=\"source\" ref=\"1014\"/>\n\t\t\t\t\t\t<reference key=\"destination\" ref=\"238351151\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<int key=\"connectionID\">435</int>\n\t\t\t\t</object>\n\t\t\t\t<object class=\"IBConnectionRecord\">\n\t\t\t\t\t<object class=\"IBActionConnection\" key=\"connection\">\n\t\t\t\t\t\t<string key=\"label\">pasteFont:</string>\n\t\t\t\t\t\t<reference key=\"source\" ref=\"1014\"/>\n\t\t\t\t\t\t<reference key=\"destination\" ref=\"393423671\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<int key=\"connectionID\">436</int>\n\t\t\t\t</object>\n\t\t\t\t<object class=\"IBConnectionRecord\">\n\t\t\t\t\t<object class=\"IBActionConnection\" key=\"connection\">\n\t\t\t\t\t\t<string key=\"label\">unscript:</string>\n\t\t\t\t\t\t<reference key=\"source\" ref=\"1014\"/>\n\t\t\t\t\t\t<reference key=\"destination\" ref=\"257962622\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<int key=\"connectionID\">437</int>\n\t\t\t\t</object>\n\t\t\t\t<object class=\"IBConnectionRecord\">\n\t\t\t\t\t<object class=\"IBActionConnection\" key=\"connection\">\n\t\t\t\t\t\t<string key=\"label\">useStandardKerning:</string>\n\t\t\t\t\t\t<reference key=\"source\" ref=\"1014\"/>\n\t\t\t\t\t\t<reference key=\"destination\" ref=\"252969304\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<int key=\"connectionID\">438</int>\n\t\t\t\t</object>\n\t\t\t\t<object class=\"IBConnectionRecord\">\n\t\t\t\t\t<object class=\"IBActionConnection\" key=\"connection\">\n\t\t\t\t\t\t<string key=\"label\">useStandardLigatures:</string>\n\t\t\t\t\t\t<reference key=\"source\" ref=\"1014\"/>\n\t\t\t\t\t\t<reference key=\"destination\" ref=\"706297211\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<int key=\"connectionID\">439</int>\n\t\t\t\t</object>\n\t\t\t\t<object class=\"IBConnectionRecord\">\n\t\t\t\t\t<object class=\"IBActionConnection\" key=\"connection\">\n\t\t\t\t\t\t<string key=\"label\">turnOffLigatures:</string>\n\t\t\t\t\t\t<reference key=\"source\" ref=\"1014\"/>\n\t\t\t\t\t\t<reference key=\"destination\" ref=\"568384683\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<int key=\"connectionID\">440</int>\n\t\t\t\t</object>\n\t\t\t\t<object class=\"IBConnectionRecord\">\n\t\t\t\t\t<object class=\"IBActionConnection\" key=\"connection\">\n\t\t\t\t\t\t<string key=\"label\">turnOffKerning:</string>\n\t\t\t\t\t\t<reference key=\"source\" ref=\"1014\"/>\n\t\t\t\t\t\t<reference key=\"destination\" ref=\"766922938\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<int key=\"connectionID\">441</int>\n\t\t\t\t</object>\n\t\t\t\t<object class=\"IBConnectionRecord\">\n\t\t\t\t\t<object class=\"IBActionConnection\" key=\"connection\">\n\t\t\t\t\t\t<string key=\"label\">terminate:</string>\n\t\t\t\t\t\t<reference key=\"source\" ref=\"1050\"/>\n\t\t\t\t\t\t<reference key=\"destination\" ref=\"632727374\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<int key=\"connectionID\">449</int>\n\t\t\t\t</object>\n\t\t\t\t<object class=\"IBConnectionRecord\">\n\t\t\t\t\t<object class=\"IBActionConnection\" key=\"connection\">\n\t\t\t\t\t\t<string key=\"label\">toggleAutomaticSpellingCorrection:</string>\n\t\t\t\t\t\t<reference key=\"source\" ref=\"1014\"/>\n\t\t\t\t\t\t<reference key=\"destination\" ref=\"795346622\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<int key=\"connectionID\">456</int>\n\t\t\t\t</object>\n\t\t\t\t<object class=\"IBConnectionRecord\">\n\t\t\t\t\t<object class=\"IBActionConnection\" key=\"connection\">\n\t\t\t\t\t\t<string key=\"label\">orderFrontSubstitutionsPanel:</string>\n\t\t\t\t\t\t<reference key=\"source\" ref=\"1014\"/>\n\t\t\t\t\t\t<reference key=\"destination\" ref=\"65139061\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<int key=\"connectionID\">458</int>\n\t\t\t\t</object>\n\t\t\t\t<object class=\"IBConnectionRecord\">\n\t\t\t\t\t<object class=\"IBActionConnection\" key=\"connection\">\n\t\t\t\t\t\t<string key=\"label\">toggleAutomaticDashSubstitution:</string>\n\t\t\t\t\t\t<reference key=\"source\" ref=\"1014\"/>\n\t\t\t\t\t\t<reference key=\"destination\" ref=\"672708820\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<int key=\"connectionID\">461</int>\n\t\t\t\t</object>\n\t\t\t\t<object class=\"IBConnectionRecord\">\n\t\t\t\t\t<object class=\"IBActionConnection\" key=\"connection\">\n\t\t\t\t\t\t<string key=\"label\">toggleAutomaticTextReplacement:</string>\n\t\t\t\t\t\t<reference key=\"source\" ref=\"1014\"/>\n\t\t\t\t\t\t<reference key=\"destination\" ref=\"537092702\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<int key=\"connectionID\">463</int>\n\t\t\t\t</object>\n\t\t\t\t<object class=\"IBConnectionRecord\">\n\t\t\t\t\t<object class=\"IBActionConnection\" key=\"connection\">\n\t\t\t\t\t\t<string key=\"label\">uppercaseWord:</string>\n\t\t\t\t\t\t<reference key=\"source\" ref=\"1014\"/>\n\t\t\t\t\t\t<reference key=\"destination\" ref=\"1060694897\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<int key=\"connectionID\">464</int>\n\t\t\t\t</object>\n\t\t\t\t<object class=\"IBConnectionRecord\">\n\t\t\t\t\t<object class=\"IBActionConnection\" key=\"connection\">\n\t\t\t\t\t\t<string key=\"label\">capitalizeWord:</string>\n\t\t\t\t\t\t<reference key=\"source\" ref=\"1014\"/>\n\t\t\t\t\t\t<reference key=\"destination\" ref=\"56570060\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<int key=\"connectionID\">467</int>\n\t\t\t\t</object>\n\t\t\t\t<object class=\"IBConnectionRecord\">\n\t\t\t\t\t<object class=\"IBActionConnection\" key=\"connection\">\n\t\t\t\t\t\t<string key=\"label\">lowercaseWord:</string>\n\t\t\t\t\t\t<reference key=\"source\" ref=\"1014\"/>\n\t\t\t\t\t\t<reference key=\"destination\" ref=\"879586729\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<int key=\"connectionID\">468</int>\n\t\t\t\t</object>\n\t\t\t\t<object class=\"IBConnectionRecord\">\n\t\t\t\t\t<object class=\"IBActionConnection\" key=\"connection\">\n\t\t\t\t\t\t<string key=\"label\">pasteAsPlainText:</string>\n\t\t\t\t\t\t<reference key=\"source\" ref=\"1014\"/>\n\t\t\t\t\t\t<reference key=\"destination\" ref=\"82994268\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<int key=\"connectionID\">486</int>\n\t\t\t\t</object>\n\t\t\t\t<object class=\"IBConnectionRecord\">\n\t\t\t\t\t<object class=\"IBActionConnection\" key=\"connection\">\n\t\t\t\t\t\t<string key=\"label\">performFindPanelAction:</string>\n\t\t\t\t\t\t<reference key=\"source\" ref=\"1014\"/>\n\t\t\t\t\t\t<reference key=\"destination\" ref=\"326711663\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<int key=\"connectionID\">487</int>\n\t\t\t\t</object>\n\t\t\t\t<object class=\"IBConnectionRecord\">\n\t\t\t\t\t<object class=\"IBActionConnection\" key=\"connection\">\n\t\t\t\t\t\t<string key=\"label\">performFindPanelAction:</string>\n\t\t\t\t\t\t<reference key=\"source\" ref=\"1014\"/>\n\t\t\t\t\t\t<reference key=\"destination\" ref=\"270902937\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<int key=\"connectionID\">488</int>\n\t\t\t\t</object>\n\t\t\t\t<object class=\"IBConnectionRecord\">\n\t\t\t\t\t<object class=\"IBActionConnection\" key=\"connection\">\n\t\t\t\t\t\t<string key=\"label\">performFindPanelAction:</string>\n\t\t\t\t\t\t<reference key=\"source\" ref=\"1014\"/>\n\t\t\t\t\t\t<reference key=\"destination\" ref=\"159080638\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<int key=\"connectionID\">489</int>\n\t\t\t\t</object>\n\t\t\t\t<object class=\"IBConnectionRecord\">\n\t\t\t\t\t<object class=\"IBActionConnection\" key=\"connection\">\n\t\t\t\t\t\t<string key=\"label\">showHelp:</string>\n\t\t\t\t\t\t<reference key=\"source\" ref=\"1014\"/>\n\t\t\t\t\t\t<reference key=\"destination\" ref=\"105068016\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<int key=\"connectionID\">493</int>\n\t\t\t\t</object>\n\t\t\t\t<object class=\"IBConnectionRecord\">\n\t\t\t\t\t<object class=\"IBOutletConnection\" key=\"connection\">\n\t\t\t\t\t\t<string key=\"label\">delegate</string>\n\t\t\t\t\t\t<reference key=\"source\" ref=\"1021\"/>\n\t\t\t\t\t\t<reference key=\"destination\" ref=\"976324537\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<int key=\"connectionID\">495</int>\n\t\t\t\t</object>\n\t\t\t\t<object class=\"IBConnectionRecord\">\n\t\t\t\t\t<object class=\"IBActionConnection\" key=\"connection\">\n\t\t\t\t\t\t<string key=\"label\">alignCenter:</string>\n\t\t\t\t\t\t<reference key=\"source\" ref=\"1014\"/>\n\t\t\t\t\t\t<reference key=\"destination\" ref=\"630155264\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<int key=\"connectionID\">518</int>\n\t\t\t\t</object>\n\t\t\t\t<object class=\"IBConnectionRecord\">\n\t\t\t\t\t<object class=\"IBActionConnection\" key=\"connection\">\n\t\t\t\t\t\t<string key=\"label\">pasteRuler:</string>\n\t\t\t\t\t\t<reference key=\"source\" ref=\"1014\"/>\n\t\t\t\t\t\t<reference key=\"destination\" ref=\"883618387\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<int key=\"connectionID\">519</int>\n\t\t\t\t</object>\n\t\t\t\t<object class=\"IBConnectionRecord\">\n\t\t\t\t\t<object class=\"IBActionConnection\" key=\"connection\">\n\t\t\t\t\t\t<string key=\"label\">toggleRuler:</string>\n\t\t\t\t\t\t<reference key=\"source\" ref=\"1014\"/>\n\t\t\t\t\t\t<reference key=\"destination\" ref=\"644046920\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<int key=\"connectionID\">520</int>\n\t\t\t\t</object>\n\t\t\t\t<object class=\"IBConnectionRecord\">\n\t\t\t\t\t<object class=\"IBActionConnection\" key=\"connection\">\n\t\t\t\t\t\t<string key=\"label\">alignRight:</string>\n\t\t\t\t\t\t<reference key=\"source\" ref=\"1014\"/>\n\t\t\t\t\t\t<reference key=\"destination\" ref=\"512868991\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<int key=\"connectionID\">521</int>\n\t\t\t\t</object>\n\t\t\t\t<object class=\"IBConnectionRecord\">\n\t\t\t\t\t<object class=\"IBActionConnection\" key=\"connection\">\n\t\t\t\t\t\t<string key=\"label\">copyRuler:</string>\n\t\t\t\t\t\t<reference key=\"source\" ref=\"1014\"/>\n\t\t\t\t\t\t<reference key=\"destination\" ref=\"231811626\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<int key=\"connectionID\">522</int>\n\t\t\t\t</object>\n\t\t\t\t<object class=\"IBConnectionRecord\">\n\t\t\t\t\t<object class=\"IBActionConnection\" key=\"connection\">\n\t\t\t\t\t\t<string key=\"label\">alignJustified:</string>\n\t\t\t\t\t\t<reference key=\"source\" ref=\"1014\"/>\n\t\t\t\t\t\t<reference key=\"destination\" ref=\"945678886\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<int key=\"connectionID\">523</int>\n\t\t\t\t</object>\n\t\t\t\t<object class=\"IBConnectionRecord\">\n\t\t\t\t\t<object class=\"IBActionConnection\" key=\"connection\">\n\t\t\t\t\t\t<string key=\"label\">alignLeft:</string>\n\t\t\t\t\t\t<reference key=\"source\" ref=\"1014\"/>\n\t\t\t\t\t\t<reference key=\"destination\" ref=\"875092757\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<int key=\"connectionID\">524</int>\n\t\t\t\t</object>\n\t\t\t\t<object class=\"IBConnectionRecord\">\n\t\t\t\t\t<object class=\"IBActionConnection\" key=\"connection\">\n\t\t\t\t\t\t<string key=\"label\">makeBaseWritingDirectionNatural:</string>\n\t\t\t\t\t\t<reference key=\"source\" ref=\"1014\"/>\n\t\t\t\t\t\t<reference key=\"destination\" ref=\"551969625\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<int key=\"connectionID\">525</int>\n\t\t\t\t</object>\n\t\t\t\t<object class=\"IBConnectionRecord\">\n\t\t\t\t\t<object class=\"IBActionConnection\" key=\"connection\">\n\t\t\t\t\t\t<string key=\"label\">makeBaseWritingDirectionLeftToRight:</string>\n\t\t\t\t\t\t<reference key=\"source\" ref=\"1014\"/>\n\t\t\t\t\t\t<reference key=\"destination\" ref=\"249532473\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<int key=\"connectionID\">526</int>\n\t\t\t\t</object>\n\t\t\t\t<object class=\"IBConnectionRecord\">\n\t\t\t\t\t<object class=\"IBActionConnection\" key=\"connection\">\n\t\t\t\t\t\t<string key=\"label\">makeBaseWritingDirectionRightToLeft:</string>\n\t\t\t\t\t\t<reference key=\"source\" ref=\"1014\"/>\n\t\t\t\t\t\t<reference key=\"destination\" ref=\"607364498\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<int key=\"connectionID\">527</int>\n\t\t\t\t</object>\n\t\t\t\t<object class=\"IBConnectionRecord\">\n\t\t\t\t\t<object class=\"IBActionConnection\" key=\"connection\">\n\t\t\t\t\t\t<string key=\"label\">makeTextWritingDirectionNatural:</string>\n\t\t\t\t\t\t<reference key=\"source\" ref=\"1014\"/>\n\t\t\t\t\t\t<reference key=\"destination\" ref=\"380031999\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<int key=\"connectionID\">528</int>\n\t\t\t\t</object>\n\t\t\t\t<object class=\"IBConnectionRecord\">\n\t\t\t\t\t<object class=\"IBActionConnection\" key=\"connection\">\n\t\t\t\t\t\t<string key=\"label\">makeTextWritingDirectionLeftToRight:</string>\n\t\t\t\t\t\t<reference key=\"source\" ref=\"1014\"/>\n\t\t\t\t\t\t<reference key=\"destination\" ref=\"825984362\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<int key=\"connectionID\">529</int>\n\t\t\t\t</object>\n\t\t\t\t<object class=\"IBConnectionRecord\">\n\t\t\t\t\t<object class=\"IBActionConnection\" key=\"connection\">\n\t\t\t\t\t\t<string key=\"label\">makeTextWritingDirectionRightToLeft:</string>\n\t\t\t\t\t\t<reference key=\"source\" ref=\"1014\"/>\n\t\t\t\t\t\t<reference key=\"destination\" ref=\"560145579\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<int key=\"connectionID\">530</int>\n\t\t\t\t</object>\n\t\t\t\t<object class=\"IBConnectionRecord\">\n\t\t\t\t\t<object class=\"IBOutletConnection\" key=\"connection\">\n\t\t\t\t\t\t<string key=\"label\">window</string>\n\t\t\t\t\t\t<reference key=\"source\" ref=\"976324537\"/>\n\t\t\t\t\t\t<reference key=\"destination\" ref=\"972006081\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<int key=\"connectionID\">532</int>\n\t\t\t\t</object>\n\t\t\t\t<object class=\"IBConnectionRecord\">\n\t\t\t\t\t<object class=\"IBOutletConnection\" key=\"connection\">\n\t\t\t\t\t\t<string key=\"label\">password</string>\n\t\t\t\t\t\t<reference key=\"source\" ref=\"976324537\"/>\n\t\t\t\t\t\t<reference key=\"destination\" ref=\"394479719\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<int key=\"connectionID\">539</int>\n\t\t\t\t</object>\n\t\t\t\t<object class=\"IBConnectionRecord\">\n\t\t\t\t\t<object class=\"IBOutletConnection\" key=\"connection\">\n\t\t\t\t\t\t<string key=\"label\">username</string>\n\t\t\t\t\t\t<reference key=\"source\" ref=\"976324537\"/>\n\t\t\t\t\t\t<reference key=\"destination\" ref=\"765794976\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<int key=\"connectionID\">540</int>\n\t\t\t\t</object>\n\t\t\t\t<object class=\"IBConnectionRecord\">\n\t\t\t\t\t<object class=\"IBActionConnection\" key=\"connection\">\n\t\t\t\t\t\t<string key=\"label\">loginAndPlay:</string>\n\t\t\t\t\t\t<reference key=\"source\" ref=\"976324537\"/>\n\t\t\t\t\t\t<reference key=\"destination\" ref=\"327821739\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<int key=\"connectionID\">541</int>\n\t\t\t\t</object>\n\t\t\t\t<object class=\"IBConnectionRecord\">\n\t\t\t\t\t<object class=\"IBOutletConnection\" key=\"connection\">\n\t\t\t\t\t\t<string key=\"label\">log</string>\n\t\t\t\t\t\t<reference key=\"source\" ref=\"976324537\"/>\n\t\t\t\t\t\t<reference key=\"destination\" ref=\"167731747\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<int key=\"connectionID\">544</int>\n\t\t\t\t</object>\n\t\t\t\t<object class=\"IBConnectionRecord\">\n\t\t\t\t\t<object class=\"IBBindingConnection\" key=\"connection\">\n\t\t\t\t\t\t<string key=\"label\">value: values.username</string>\n\t\t\t\t\t\t<reference key=\"source\" ref=\"765794976\"/>\n\t\t\t\t\t\t<reference key=\"destination\" ref=\"1007787480\"/>\n\t\t\t\t\t\t<object class=\"NSNibBindingConnector\" key=\"connector\">\n\t\t\t\t\t\t\t<reference key=\"NSSource\" ref=\"765794976\"/>\n\t\t\t\t\t\t\t<reference key=\"NSDestination\" ref=\"1007787480\"/>\n\t\t\t\t\t\t\t<string key=\"NSLabel\">value: values.username</string>\n\t\t\t\t\t\t\t<string key=\"NSBinding\">value</string>\n\t\t\t\t\t\t\t<string key=\"NSKeyPath\">values.username</string>\n\t\t\t\t\t\t\t<int key=\"NSNibBindingConnectorVersion\">2</int>\n\t\t\t\t\t\t</object>\n\t\t\t\t\t</object>\n\t\t\t\t\t<int key=\"connectionID\">547</int>\n\t\t\t\t</object>\n\t\t\t\t<object class=\"IBConnectionRecord\">\n\t\t\t\t\t<object class=\"IBBindingConnection\" key=\"connection\">\n\t\t\t\t\t\t<string key=\"label\">value: values.password</string>\n\t\t\t\t\t\t<reference key=\"source\" ref=\"394479719\"/>\n\t\t\t\t\t\t<reference key=\"destination\" ref=\"1007787480\"/>\n\t\t\t\t\t\t<object class=\"NSNibBindingConnector\" key=\"connector\">\n\t\t\t\t\t\t\t<reference key=\"NSSource\" ref=\"394479719\"/>\n\t\t\t\t\t\t\t<reference key=\"NSDestination\" ref=\"1007787480\"/>\n\t\t\t\t\t\t\t<string key=\"NSLabel\">value: values.password</string>\n\t\t\t\t\t\t\t<string key=\"NSBinding\">value</string>\n\t\t\t\t\t\t\t<string key=\"NSKeyPath\">values.password</string>\n\t\t\t\t\t\t\t<int key=\"NSNibBindingConnectorVersion\">2</int>\n\t\t\t\t\t\t</object>\n\t\t\t\t\t</object>\n\t\t\t\t\t<int key=\"connectionID\">549</int>\n\t\t\t\t</object>\n\t\t\t\t<object class=\"IBConnectionRecord\">\n\t\t\t\t\t<object class=\"IBActionConnection\" key=\"connection\">\n\t\t\t\t\t\t<string key=\"label\">togglePlay:</string>\n\t\t\t\t\t\t<reference key=\"source\" ref=\"976324537\"/>\n\t\t\t\t\t\t<reference key=\"destination\" ref=\"935404353\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<int key=\"connectionID\">554</int>\n\t\t\t\t</object>\n\t\t\t\t<object class=\"IBConnectionRecord\">\n\t\t\t\t\t<object class=\"IBActionConnection\" key=\"connection\">\n\t\t\t\t\t\t<string key=\"label\">playARandomSong:</string>\n\t\t\t\t\t\t<reference key=\"source\" ref=\"976324537\"/>\n\t\t\t\t\t\t<reference key=\"destination\" ref=\"264769268\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<int key=\"connectionID\">555</int>\n\t\t\t\t</object>\n\t\t\t\t<object class=\"IBConnectionRecord\">\n\t\t\t\t\t<object class=\"IBOutletConnection\" key=\"connection\">\n\t\t\t\t\t\t<string key=\"label\">playButton</string>\n\t\t\t\t\t\t<reference key=\"source\" ref=\"976324537\"/>\n\t\t\t\t\t\t<reference key=\"destination\" ref=\"935404353\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<int key=\"connectionID\">556</int>\n\t\t\t\t</object>\n\t\t\t\t<object class=\"IBConnectionRecord\">\n\t\t\t\t\t<object class=\"IBOutletConnection\" key=\"connection\">\n\t\t\t\t\t\t<string key=\"label\">status</string>\n\t\t\t\t\t\t<reference key=\"source\" ref=\"976324537\"/>\n\t\t\t\t\t\t<reference key=\"destination\" ref=\"161503078\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<int key=\"connectionID\">563</int>\n\t\t\t\t</object>\n\t\t\t</object>\n\t\t\t<object class=\"IBMutableOrderedSet\" key=\"objectRecords\">\n\t\t\t\t<object class=\"NSArray\" key=\"orderedObjects\">\n\t\t\t\t\t<bool key=\"EncodedWithXMLCoder\">YES</bool>\n\t\t\t\t\t<object class=\"IBObjectRecord\">\n\t\t\t\t\t\t<int key=\"objectID\">0</int>\n\t\t\t\t\t\t<reference key=\"object\" ref=\"0\"/>\n\t\t\t\t\t\t<reference key=\"children\" ref=\"1048\"/>\n\t\t\t\t\t\t<nil key=\"parent\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<object class=\"IBObjectRecord\">\n\t\t\t\t\t\t<int key=\"objectID\">-2</int>\n\t\t\t\t\t\t<reference key=\"object\" ref=\"1021\"/>\n\t\t\t\t\t\t<reference key=\"parent\" ref=\"0\"/>\n\t\t\t\t\t\t<string key=\"objectName\">File's Owner</string>\n\t\t\t\t\t</object>\n\t\t\t\t\t<object class=\"IBObjectRecord\">\n\t\t\t\t\t\t<int key=\"objectID\">-1</int>\n\t\t\t\t\t\t<reference key=\"object\" ref=\"1014\"/>\n\t\t\t\t\t\t<reference key=\"parent\" ref=\"0\"/>\n\t\t\t\t\t\t<string key=\"objectName\">First Responder</string>\n\t\t\t\t\t</object>\n\t\t\t\t\t<object class=\"IBObjectRecord\">\n\t\t\t\t\t\t<int key=\"objectID\">-3</int>\n\t\t\t\t\t\t<reference key=\"object\" ref=\"1050\"/>\n\t\t\t\t\t\t<reference key=\"parent\" ref=\"0\"/>\n\t\t\t\t\t\t<string key=\"objectName\">Application</string>\n\t\t\t\t\t</object>\n\t\t\t\t\t<object class=\"IBObjectRecord\">\n\t\t\t\t\t\t<int key=\"objectID\">29</int>\n\t\t\t\t\t\t<reference key=\"object\" ref=\"649796088\"/>\n\t\t\t\t\t\t<object class=\"NSMutableArray\" key=\"children\">\n\t\t\t\t\t\t\t<bool key=\"EncodedWithXMLCoder\">YES</bool>\n\t\t\t\t\t\t\t<reference ref=\"713487014\"/>\n\t\t\t\t\t\t\t<reference ref=\"694149608\"/>\n\t\t\t\t\t\t\t<reference ref=\"952259628\"/>\n\t\t\t\t\t\t\t<reference ref=\"379814623\"/>\n\t\t\t\t\t\t\t<reference ref=\"586577488\"/>\n\t\t\t\t\t\t\t<reference ref=\"302598603\"/>\n\t\t\t\t\t\t\t<reference ref=\"448692316\"/>\n\t\t\t\t\t\t</object>\n\t\t\t\t\t\t<reference key=\"parent\" ref=\"0\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<object class=\"IBObjectRecord\">\n\t\t\t\t\t\t<int key=\"objectID\">19</int>\n\t\t\t\t\t\t<reference key=\"object\" ref=\"713487014\"/>\n\t\t\t\t\t\t<object class=\"NSMutableArray\" key=\"children\">\n\t\t\t\t\t\t\t<bool key=\"EncodedWithXMLCoder\">YES</bool>\n\t\t\t\t\t\t\t<reference ref=\"835318025\"/>\n\t\t\t\t\t\t</object>\n\t\t\t\t\t\t<reference key=\"parent\" ref=\"649796088\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<object class=\"IBObjectRecord\">\n\t\t\t\t\t\t<int key=\"objectID\">56</int>\n\t\t\t\t\t\t<reference key=\"object\" ref=\"694149608\"/>\n\t\t\t\t\t\t<object class=\"NSMutableArray\" key=\"children\">\n\t\t\t\t\t\t\t<bool key=\"EncodedWithXMLCoder\">YES</bool>\n\t\t\t\t\t\t\t<reference ref=\"110575045\"/>\n\t\t\t\t\t\t</object>\n\t\t\t\t\t\t<reference key=\"parent\" ref=\"649796088\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<object class=\"IBObjectRecord\">\n\t\t\t\t\t\t<int key=\"objectID\">217</int>\n\t\t\t\t\t\t<reference key=\"object\" ref=\"952259628\"/>\n\t\t\t\t\t\t<object class=\"NSMutableArray\" key=\"children\">\n\t\t\t\t\t\t\t<bool key=\"EncodedWithXMLCoder\">YES</bool>\n\t\t\t\t\t\t\t<reference ref=\"789758025\"/>\n\t\t\t\t\t\t</object>\n\t\t\t\t\t\t<reference key=\"parent\" ref=\"649796088\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<object class=\"IBObjectRecord\">\n\t\t\t\t\t\t<int key=\"objectID\">83</int>\n\t\t\t\t\t\t<reference key=\"object\" ref=\"379814623\"/>\n\t\t\t\t\t\t<object class=\"NSMutableArray\" key=\"children\">\n\t\t\t\t\t\t\t<bool key=\"EncodedWithXMLCoder\">YES</bool>\n\t\t\t\t\t\t\t<reference ref=\"720053764\"/>\n\t\t\t\t\t\t</object>\n\t\t\t\t\t\t<reference key=\"parent\" ref=\"649796088\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<object class=\"IBObjectRecord\">\n\t\t\t\t\t\t<int key=\"objectID\">81</int>\n\t\t\t\t\t\t<reference key=\"object\" ref=\"720053764\"/>\n\t\t\t\t\t\t<object class=\"NSMutableArray\" key=\"children\">\n\t\t\t\t\t\t\t<bool key=\"EncodedWithXMLCoder\">YES</bool>\n\t\t\t\t\t\t\t<reference ref=\"1023925487\"/>\n\t\t\t\t\t\t\t<reference ref=\"117038363\"/>\n\t\t\t\t\t\t\t<reference ref=\"49223823\"/>\n\t\t\t\t\t\t\t<reference ref=\"722745758\"/>\n\t\t\t\t\t\t\t<reference ref=\"705341025\"/>\n\t\t\t\t\t\t\t<reference ref=\"1025936716\"/>\n\t\t\t\t\t\t\t<reference ref=\"294629803\"/>\n\t\t\t\t\t\t\t<reference ref=\"776162233\"/>\n\t\t\t\t\t\t\t<reference ref=\"425164168\"/>\n\t\t\t\t\t\t\t<reference ref=\"579971712\"/>\n\t\t\t\t\t\t\t<reference ref=\"1010469920\"/>\n\t\t\t\t\t\t</object>\n\t\t\t\t\t\t<reference key=\"parent\" ref=\"379814623\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<object class=\"IBObjectRecord\">\n\t\t\t\t\t\t<int key=\"objectID\">75</int>\n\t\t\t\t\t\t<reference key=\"object\" ref=\"1023925487\"/>\n\t\t\t\t\t\t<reference key=\"parent\" ref=\"720053764\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<object class=\"IBObjectRecord\">\n\t\t\t\t\t\t<int key=\"objectID\">80</int>\n\t\t\t\t\t\t<reference key=\"object\" ref=\"117038363\"/>\n\t\t\t\t\t\t<reference key=\"parent\" ref=\"720053764\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<object class=\"IBObjectRecord\">\n\t\t\t\t\t\t<int key=\"objectID\">78</int>\n\t\t\t\t\t\t<reference key=\"object\" ref=\"49223823\"/>\n\t\t\t\t\t\t<reference key=\"parent\" ref=\"720053764\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<object class=\"IBObjectRecord\">\n\t\t\t\t\t\t<int key=\"objectID\">72</int>\n\t\t\t\t\t\t<reference key=\"object\" ref=\"722745758\"/>\n\t\t\t\t\t\t<reference key=\"parent\" ref=\"720053764\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<object class=\"IBObjectRecord\">\n\t\t\t\t\t\t<int key=\"objectID\">82</int>\n\t\t\t\t\t\t<reference key=\"object\" ref=\"705341025\"/>\n\t\t\t\t\t\t<reference key=\"parent\" ref=\"720053764\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<object class=\"IBObjectRecord\">\n\t\t\t\t\t\t<int key=\"objectID\">124</int>\n\t\t\t\t\t\t<reference key=\"object\" ref=\"1025936716\"/>\n\t\t\t\t\t\t<object class=\"NSMutableArray\" key=\"children\">\n\t\t\t\t\t\t\t<bool key=\"EncodedWithXMLCoder\">YES</bool>\n\t\t\t\t\t\t\t<reference ref=\"1065607017\"/>\n\t\t\t\t\t\t</object>\n\t\t\t\t\t\t<reference key=\"parent\" ref=\"720053764\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<object class=\"IBObjectRecord\">\n\t\t\t\t\t\t<int key=\"objectID\">77</int>\n\t\t\t\t\t\t<reference key=\"object\" ref=\"294629803\"/>\n\t\t\t\t\t\t<reference key=\"parent\" ref=\"720053764\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<object class=\"IBObjectRecord\">\n\t\t\t\t\t\t<int key=\"objectID\">73</int>\n\t\t\t\t\t\t<reference key=\"object\" ref=\"776162233\"/>\n\t\t\t\t\t\t<reference key=\"parent\" ref=\"720053764\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<object class=\"IBObjectRecord\">\n\t\t\t\t\t\t<int key=\"objectID\">79</int>\n\t\t\t\t\t\t<reference key=\"object\" ref=\"425164168\"/>\n\t\t\t\t\t\t<reference key=\"parent\" ref=\"720053764\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<object class=\"IBObjectRecord\">\n\t\t\t\t\t\t<int key=\"objectID\">112</int>\n\t\t\t\t\t\t<reference key=\"object\" ref=\"579971712\"/>\n\t\t\t\t\t\t<reference key=\"parent\" ref=\"720053764\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<object class=\"IBObjectRecord\">\n\t\t\t\t\t\t<int key=\"objectID\">74</int>\n\t\t\t\t\t\t<reference key=\"object\" ref=\"1010469920\"/>\n\t\t\t\t\t\t<reference key=\"parent\" ref=\"720053764\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<object class=\"IBObjectRecord\">\n\t\t\t\t\t\t<int key=\"objectID\">125</int>\n\t\t\t\t\t\t<reference key=\"object\" ref=\"1065607017\"/>\n\t\t\t\t\t\t<object class=\"NSMutableArray\" key=\"children\">\n\t\t\t\t\t\t\t<bool key=\"EncodedWithXMLCoder\">YES</bool>\n\t\t\t\t\t\t\t<reference ref=\"759406840\"/>\n\t\t\t\t\t\t</object>\n\t\t\t\t\t\t<reference key=\"parent\" ref=\"1025936716\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<object class=\"IBObjectRecord\">\n\t\t\t\t\t\t<int key=\"objectID\">126</int>\n\t\t\t\t\t\t<reference key=\"object\" ref=\"759406840\"/>\n\t\t\t\t\t\t<reference key=\"parent\" ref=\"1065607017\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<object class=\"IBObjectRecord\">\n\t\t\t\t\t\t<int key=\"objectID\">205</int>\n\t\t\t\t\t\t<reference key=\"object\" ref=\"789758025\"/>\n\t\t\t\t\t\t<object class=\"NSMutableArray\" key=\"children\">\n\t\t\t\t\t\t\t<bool key=\"EncodedWithXMLCoder\">YES</bool>\n\t\t\t\t\t\t\t<reference ref=\"437104165\"/>\n\t\t\t\t\t\t\t<reference ref=\"583158037\"/>\n\t\t\t\t\t\t\t<reference ref=\"1058277027\"/>\n\t\t\t\t\t\t\t<reference ref=\"212016141\"/>\n\t\t\t\t\t\t\t<reference ref=\"296257095\"/>\n\t\t\t\t\t\t\t<reference ref=\"29853731\"/>\n\t\t\t\t\t\t\t<reference ref=\"860595796\"/>\n\t\t\t\t\t\t\t<reference ref=\"1040322652\"/>\n\t\t\t\t\t\t\t<reference ref=\"790794224\"/>\n\t\t\t\t\t\t\t<reference ref=\"892235320\"/>\n\t\t\t\t\t\t\t<reference ref=\"972420730\"/>\n\t\t\t\t\t\t\t<reference ref=\"676164635\"/>\n\t\t\t\t\t\t\t<reference ref=\"507821607\"/>\n\t\t\t\t\t\t\t<reference ref=\"288088188\"/>\n\t\t\t\t\t\t\t<reference ref=\"82994268\"/>\n\t\t\t\t\t\t</object>\n\t\t\t\t\t\t<reference key=\"parent\" ref=\"952259628\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<object class=\"IBObjectRecord\">\n\t\t\t\t\t\t<int key=\"objectID\">202</int>\n\t\t\t\t\t\t<reference key=\"object\" ref=\"437104165\"/>\n\t\t\t\t\t\t<reference key=\"parent\" ref=\"789758025\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<object class=\"IBObjectRecord\">\n\t\t\t\t\t\t<int key=\"objectID\">198</int>\n\t\t\t\t\t\t<reference key=\"object\" ref=\"583158037\"/>\n\t\t\t\t\t\t<reference key=\"parent\" ref=\"789758025\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<object class=\"IBObjectRecord\">\n\t\t\t\t\t\t<int key=\"objectID\">207</int>\n\t\t\t\t\t\t<reference key=\"object\" ref=\"1058277027\"/>\n\t\t\t\t\t\t<reference key=\"parent\" ref=\"789758025\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<object class=\"IBObjectRecord\">\n\t\t\t\t\t\t<int key=\"objectID\">214</int>\n\t\t\t\t\t\t<reference key=\"object\" ref=\"212016141\"/>\n\t\t\t\t\t\t<reference key=\"parent\" ref=\"789758025\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<object class=\"IBObjectRecord\">\n\t\t\t\t\t\t<int key=\"objectID\">199</int>\n\t\t\t\t\t\t<reference key=\"object\" ref=\"296257095\"/>\n\t\t\t\t\t\t<reference key=\"parent\" ref=\"789758025\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<object class=\"IBObjectRecord\">\n\t\t\t\t\t\t<int key=\"objectID\">203</int>\n\t\t\t\t\t\t<reference key=\"object\" ref=\"29853731\"/>\n\t\t\t\t\t\t<reference key=\"parent\" ref=\"789758025\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<object class=\"IBObjectRecord\">\n\t\t\t\t\t\t<int key=\"objectID\">197</int>\n\t\t\t\t\t\t<reference key=\"object\" ref=\"860595796\"/>\n\t\t\t\t\t\t<reference key=\"parent\" ref=\"789758025\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<object class=\"IBObjectRecord\">\n\t\t\t\t\t\t<int key=\"objectID\">206</int>\n\t\t\t\t\t\t<reference key=\"object\" ref=\"1040322652\"/>\n\t\t\t\t\t\t<reference key=\"parent\" ref=\"789758025\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<object class=\"IBObjectRecord\">\n\t\t\t\t\t\t<int key=\"objectID\">215</int>\n\t\t\t\t\t\t<reference key=\"object\" ref=\"790794224\"/>\n\t\t\t\t\t\t<reference key=\"parent\" ref=\"789758025\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<object class=\"IBObjectRecord\">\n\t\t\t\t\t\t<int key=\"objectID\">218</int>\n\t\t\t\t\t\t<reference key=\"object\" ref=\"892235320\"/>\n\t\t\t\t\t\t<object class=\"NSMutableArray\" key=\"children\">\n\t\t\t\t\t\t\t<bool key=\"EncodedWithXMLCoder\">YES</bool>\n\t\t\t\t\t\t\t<reference ref=\"963351320\"/>\n\t\t\t\t\t\t</object>\n\t\t\t\t\t\t<reference key=\"parent\" ref=\"789758025\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<object class=\"IBObjectRecord\">\n\t\t\t\t\t\t<int key=\"objectID\">216</int>\n\t\t\t\t\t\t<reference key=\"object\" ref=\"972420730\"/>\n\t\t\t\t\t\t<object class=\"NSMutableArray\" key=\"children\">\n\t\t\t\t\t\t\t<bool key=\"EncodedWithXMLCoder\">YES</bool>\n\t\t\t\t\t\t\t<reference ref=\"769623530\"/>\n\t\t\t\t\t\t</object>\n\t\t\t\t\t\t<reference key=\"parent\" ref=\"789758025\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<object class=\"IBObjectRecord\">\n\t\t\t\t\t\t<int key=\"objectID\">200</int>\n\t\t\t\t\t\t<reference key=\"object\" ref=\"769623530\"/>\n\t\t\t\t\t\t<object class=\"NSMutableArray\" key=\"children\">\n\t\t\t\t\t\t\t<bool key=\"EncodedWithXMLCoder\">YES</bool>\n\t\t\t\t\t\t\t<reference ref=\"948374510\"/>\n\t\t\t\t\t\t\t<reference ref=\"96193923\"/>\n\t\t\t\t\t\t\t<reference ref=\"679648819\"/>\n\t\t\t\t\t\t\t<reference ref=\"967646866\"/>\n\t\t\t\t\t\t\t<reference ref=\"859480356\"/>\n\t\t\t\t\t\t\t<reference ref=\"795346622\"/>\n\t\t\t\t\t\t</object>\n\t\t\t\t\t\t<reference key=\"parent\" ref=\"972420730\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<object class=\"IBObjectRecord\">\n\t\t\t\t\t\t<int key=\"objectID\">219</int>\n\t\t\t\t\t\t<reference key=\"object\" ref=\"948374510\"/>\n\t\t\t\t\t\t<reference key=\"parent\" ref=\"769623530\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<object class=\"IBObjectRecord\">\n\t\t\t\t\t\t<int key=\"objectID\">201</int>\n\t\t\t\t\t\t<reference key=\"object\" ref=\"96193923\"/>\n\t\t\t\t\t\t<reference key=\"parent\" ref=\"769623530\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<object class=\"IBObjectRecord\">\n\t\t\t\t\t\t<int key=\"objectID\">204</int>\n\t\t\t\t\t\t<reference key=\"object\" ref=\"679648819\"/>\n\t\t\t\t\t\t<reference key=\"parent\" ref=\"769623530\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<object class=\"IBObjectRecord\">\n\t\t\t\t\t\t<int key=\"objectID\">220</int>\n\t\t\t\t\t\t<reference key=\"object\" ref=\"963351320\"/>\n\t\t\t\t\t\t<object class=\"NSMutableArray\" key=\"children\">\n\t\t\t\t\t\t\t<bool key=\"EncodedWithXMLCoder\">YES</bool>\n\t\t\t\t\t\t\t<reference ref=\"270902937\"/>\n\t\t\t\t\t\t\t<reference ref=\"88285865\"/>\n\t\t\t\t\t\t\t<reference ref=\"159080638\"/>\n\t\t\t\t\t\t\t<reference ref=\"326711663\"/>\n\t\t\t\t\t\t\t<reference ref=\"447796847\"/>\n\t\t\t\t\t\t</object>\n\t\t\t\t\t\t<reference key=\"parent\" ref=\"892235320\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<object class=\"IBObjectRecord\">\n\t\t\t\t\t\t<int key=\"objectID\">213</int>\n\t\t\t\t\t\t<reference key=\"object\" ref=\"270902937\"/>\n\t\t\t\t\t\t<reference key=\"parent\" ref=\"963351320\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<object class=\"IBObjectRecord\">\n\t\t\t\t\t\t<int key=\"objectID\">210</int>\n\t\t\t\t\t\t<reference key=\"object\" ref=\"88285865\"/>\n\t\t\t\t\t\t<reference key=\"parent\" ref=\"963351320\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<object class=\"IBObjectRecord\">\n\t\t\t\t\t\t<int key=\"objectID\">221</int>\n\t\t\t\t\t\t<reference key=\"object\" ref=\"159080638\"/>\n\t\t\t\t\t\t<reference key=\"parent\" ref=\"963351320\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<object class=\"IBObjectRecord\">\n\t\t\t\t\t\t<int key=\"objectID\">208</int>\n\t\t\t\t\t\t<reference key=\"object\" ref=\"326711663\"/>\n\t\t\t\t\t\t<reference key=\"parent\" ref=\"963351320\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<object class=\"IBObjectRecord\">\n\t\t\t\t\t\t<int key=\"objectID\">209</int>\n\t\t\t\t\t\t<reference key=\"object\" ref=\"447796847\"/>\n\t\t\t\t\t\t<reference key=\"parent\" ref=\"963351320\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<object class=\"IBObjectRecord\">\n\t\t\t\t\t\t<int key=\"objectID\">57</int>\n\t\t\t\t\t\t<reference key=\"object\" ref=\"110575045\"/>\n\t\t\t\t\t\t<object class=\"NSMutableArray\" key=\"children\">\n\t\t\t\t\t\t\t<bool key=\"EncodedWithXMLCoder\">YES</bool>\n\t\t\t\t\t\t\t<reference ref=\"238522557\"/>\n\t\t\t\t\t\t\t<reference ref=\"755159360\"/>\n\t\t\t\t\t\t\t<reference ref=\"908899353\"/>\n\t\t\t\t\t\t\t<reference ref=\"632727374\"/>\n\t\t\t\t\t\t\t<reference ref=\"646227648\"/>\n\t\t\t\t\t\t\t<reference ref=\"609285721\"/>\n\t\t\t\t\t\t\t<reference ref=\"481834944\"/>\n\t\t\t\t\t\t\t<reference ref=\"304266470\"/>\n\t\t\t\t\t\t\t<reference ref=\"1046388886\"/>\n\t\t\t\t\t\t\t<reference ref=\"1056857174\"/>\n\t\t\t\t\t\t\t<reference ref=\"342932134\"/>\n\t\t\t\t\t\t</object>\n\t\t\t\t\t\t<reference key=\"parent\" ref=\"694149608\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<object class=\"IBObjectRecord\">\n\t\t\t\t\t\t<int key=\"objectID\">58</int>\n\t\t\t\t\t\t<reference key=\"object\" ref=\"238522557\"/>\n\t\t\t\t\t\t<reference key=\"parent\" ref=\"110575045\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<object class=\"IBObjectRecord\">\n\t\t\t\t\t\t<int key=\"objectID\">134</int>\n\t\t\t\t\t\t<reference key=\"object\" ref=\"755159360\"/>\n\t\t\t\t\t\t<reference key=\"parent\" ref=\"110575045\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<object class=\"IBObjectRecord\">\n\t\t\t\t\t\t<int key=\"objectID\">150</int>\n\t\t\t\t\t\t<reference key=\"object\" ref=\"908899353\"/>\n\t\t\t\t\t\t<reference key=\"parent\" ref=\"110575045\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<object class=\"IBObjectRecord\">\n\t\t\t\t\t\t<int key=\"objectID\">136</int>\n\t\t\t\t\t\t<reference key=\"object\" ref=\"632727374\"/>\n\t\t\t\t\t\t<reference key=\"parent\" ref=\"110575045\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<object class=\"IBObjectRecord\">\n\t\t\t\t\t\t<int key=\"objectID\">144</int>\n\t\t\t\t\t\t<reference key=\"object\" ref=\"646227648\"/>\n\t\t\t\t\t\t<reference key=\"parent\" ref=\"110575045\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<object class=\"IBObjectRecord\">\n\t\t\t\t\t\t<int key=\"objectID\">129</int>\n\t\t\t\t\t\t<reference key=\"object\" ref=\"609285721\"/>\n\t\t\t\t\t\t<reference key=\"parent\" ref=\"110575045\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<object class=\"IBObjectRecord\">\n\t\t\t\t\t\t<int key=\"objectID\">143</int>\n\t\t\t\t\t\t<reference key=\"object\" ref=\"481834944\"/>\n\t\t\t\t\t\t<reference key=\"parent\" ref=\"110575045\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<object class=\"IBObjectRecord\">\n\t\t\t\t\t\t<int key=\"objectID\">236</int>\n\t\t\t\t\t\t<reference key=\"object\" ref=\"304266470\"/>\n\t\t\t\t\t\t<reference key=\"parent\" ref=\"110575045\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<object class=\"IBObjectRecord\">\n\t\t\t\t\t\t<int key=\"objectID\">131</int>\n\t\t\t\t\t\t<reference key=\"object\" ref=\"1046388886\"/>\n\t\t\t\t\t\t<object class=\"NSMutableArray\" key=\"children\">\n\t\t\t\t\t\t\t<bool key=\"EncodedWithXMLCoder\">YES</bool>\n\t\t\t\t\t\t\t<reference ref=\"752062318\"/>\n\t\t\t\t\t\t</object>\n\t\t\t\t\t\t<reference key=\"parent\" ref=\"110575045\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<object class=\"IBObjectRecord\">\n\t\t\t\t\t\t<int key=\"objectID\">149</int>\n\t\t\t\t\t\t<reference key=\"object\" ref=\"1056857174\"/>\n\t\t\t\t\t\t<reference key=\"parent\" ref=\"110575045\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<object class=\"IBObjectRecord\">\n\t\t\t\t\t\t<int key=\"objectID\">145</int>\n\t\t\t\t\t\t<reference key=\"object\" ref=\"342932134\"/>\n\t\t\t\t\t\t<reference key=\"parent\" ref=\"110575045\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<object class=\"IBObjectRecord\">\n\t\t\t\t\t\t<int key=\"objectID\">130</int>\n\t\t\t\t\t\t<reference key=\"object\" ref=\"752062318\"/>\n\t\t\t\t\t\t<reference key=\"parent\" ref=\"1046388886\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<object class=\"IBObjectRecord\">\n\t\t\t\t\t\t<int key=\"objectID\">24</int>\n\t\t\t\t\t\t<reference key=\"object\" ref=\"835318025\"/>\n\t\t\t\t\t\t<object class=\"NSMutableArray\" key=\"children\">\n\t\t\t\t\t\t\t<bool key=\"EncodedWithXMLCoder\">YES</bool>\n\t\t\t\t\t\t\t<reference ref=\"299356726\"/>\n\t\t\t\t\t\t\t<reference ref=\"625202149\"/>\n\t\t\t\t\t\t\t<reference ref=\"575023229\"/>\n\t\t\t\t\t\t\t<reference ref=\"1011231497\"/>\n\t\t\t\t\t\t</object>\n\t\t\t\t\t\t<reference key=\"parent\" ref=\"713487014\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<object class=\"IBObjectRecord\">\n\t\t\t\t\t\t<int key=\"objectID\">92</int>\n\t\t\t\t\t\t<reference key=\"object\" ref=\"299356726\"/>\n\t\t\t\t\t\t<reference key=\"parent\" ref=\"835318025\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<object class=\"IBObjectRecord\">\n\t\t\t\t\t\t<int key=\"objectID\">5</int>\n\t\t\t\t\t\t<reference key=\"object\" ref=\"625202149\"/>\n\t\t\t\t\t\t<reference key=\"parent\" ref=\"835318025\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<object class=\"IBObjectRecord\">\n\t\t\t\t\t\t<int key=\"objectID\">239</int>\n\t\t\t\t\t\t<reference key=\"object\" ref=\"575023229\"/>\n\t\t\t\t\t\t<reference key=\"parent\" ref=\"835318025\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<object class=\"IBObjectRecord\">\n\t\t\t\t\t\t<int key=\"objectID\">23</int>\n\t\t\t\t\t\t<reference key=\"object\" ref=\"1011231497\"/>\n\t\t\t\t\t\t<reference key=\"parent\" ref=\"835318025\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<object class=\"IBObjectRecord\">\n\t\t\t\t\t\t<int key=\"objectID\">295</int>\n\t\t\t\t\t\t<reference key=\"object\" ref=\"586577488\"/>\n\t\t\t\t\t\t<object class=\"NSMutableArray\" key=\"children\">\n\t\t\t\t\t\t\t<bool key=\"EncodedWithXMLCoder\">YES</bool>\n\t\t\t\t\t\t\t<reference ref=\"466310130\"/>\n\t\t\t\t\t\t</object>\n\t\t\t\t\t\t<reference key=\"parent\" ref=\"649796088\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<object class=\"IBObjectRecord\">\n\t\t\t\t\t\t<int key=\"objectID\">296</int>\n\t\t\t\t\t\t<reference key=\"object\" ref=\"466310130\"/>\n\t\t\t\t\t\t<object class=\"NSMutableArray\" key=\"children\">\n\t\t\t\t\t\t\t<bool key=\"EncodedWithXMLCoder\">YES</bool>\n\t\t\t\t\t\t\t<reference ref=\"102151532\"/>\n\t\t\t\t\t\t\t<reference ref=\"237841660\"/>\n\t\t\t\t\t\t</object>\n\t\t\t\t\t\t<reference key=\"parent\" ref=\"586577488\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<object class=\"IBObjectRecord\">\n\t\t\t\t\t\t<int key=\"objectID\">297</int>\n\t\t\t\t\t\t<reference key=\"object\" ref=\"102151532\"/>\n\t\t\t\t\t\t<reference key=\"parent\" ref=\"466310130\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<object class=\"IBObjectRecord\">\n\t\t\t\t\t\t<int key=\"objectID\">298</int>\n\t\t\t\t\t\t<reference key=\"object\" ref=\"237841660\"/>\n\t\t\t\t\t\t<reference key=\"parent\" ref=\"466310130\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<object class=\"IBObjectRecord\">\n\t\t\t\t\t\t<int key=\"objectID\">211</int>\n\t\t\t\t\t\t<reference key=\"object\" ref=\"676164635\"/>\n\t\t\t\t\t\t<object class=\"NSMutableArray\" key=\"children\">\n\t\t\t\t\t\t\t<bool key=\"EncodedWithXMLCoder\">YES</bool>\n\t\t\t\t\t\t\t<reference ref=\"785027613\"/>\n\t\t\t\t\t\t</object>\n\t\t\t\t\t\t<reference key=\"parent\" ref=\"789758025\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<object class=\"IBObjectRecord\">\n\t\t\t\t\t\t<int key=\"objectID\">212</int>\n\t\t\t\t\t\t<reference key=\"object\" ref=\"785027613\"/>\n\t\t\t\t\t\t<object class=\"NSMutableArray\" key=\"children\">\n\t\t\t\t\t\t\t<bool key=\"EncodedWithXMLCoder\">YES</bool>\n\t\t\t\t\t\t\t<reference ref=\"680220178\"/>\n\t\t\t\t\t\t\t<reference ref=\"731782645\"/>\n\t\t\t\t\t\t</object>\n\t\t\t\t\t\t<reference key=\"parent\" ref=\"676164635\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<object class=\"IBObjectRecord\">\n\t\t\t\t\t\t<int key=\"objectID\">195</int>\n\t\t\t\t\t\t<reference key=\"object\" ref=\"680220178\"/>\n\t\t\t\t\t\t<reference key=\"parent\" ref=\"785027613\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<object class=\"IBObjectRecord\">\n\t\t\t\t\t\t<int key=\"objectID\">196</int>\n\t\t\t\t\t\t<reference key=\"object\" ref=\"731782645\"/>\n\t\t\t\t\t\t<reference key=\"parent\" ref=\"785027613\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<object class=\"IBObjectRecord\">\n\t\t\t\t\t\t<int key=\"objectID\">346</int>\n\t\t\t\t\t\t<reference key=\"object\" ref=\"967646866\"/>\n\t\t\t\t\t\t<reference key=\"parent\" ref=\"769623530\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<object class=\"IBObjectRecord\">\n\t\t\t\t\t\t<int key=\"objectID\">348</int>\n\t\t\t\t\t\t<reference key=\"object\" ref=\"507821607\"/>\n\t\t\t\t\t\t<object class=\"NSMutableArray\" key=\"children\">\n\t\t\t\t\t\t\t<bool key=\"EncodedWithXMLCoder\">YES</bool>\n\t\t\t\t\t\t\t<reference ref=\"698887838\"/>\n\t\t\t\t\t\t</object>\n\t\t\t\t\t\t<reference key=\"parent\" ref=\"789758025\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<object class=\"IBObjectRecord\">\n\t\t\t\t\t\t<int key=\"objectID\">349</int>\n\t\t\t\t\t\t<reference key=\"object\" ref=\"698887838\"/>\n\t\t\t\t\t\t<object class=\"NSMutableArray\" key=\"children\">\n\t\t\t\t\t\t\t<bool key=\"EncodedWithXMLCoder\">YES</bool>\n\t\t\t\t\t\t\t<reference ref=\"605118523\"/>\n\t\t\t\t\t\t\t<reference ref=\"197661976\"/>\n\t\t\t\t\t\t\t<reference ref=\"708854459\"/>\n\t\t\t\t\t\t\t<reference ref=\"65139061\"/>\n\t\t\t\t\t\t\t<reference ref=\"19036812\"/>\n\t\t\t\t\t\t\t<reference ref=\"672708820\"/>\n\t\t\t\t\t\t\t<reference ref=\"537092702\"/>\n\t\t\t\t\t\t</object>\n\t\t\t\t\t\t<reference key=\"parent\" ref=\"507821607\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<object class=\"IBObjectRecord\">\n\t\t\t\t\t\t<int key=\"objectID\">350</int>\n\t\t\t\t\t\t<reference key=\"object\" ref=\"605118523\"/>\n\t\t\t\t\t\t<reference key=\"parent\" ref=\"698887838\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<object class=\"IBObjectRecord\">\n\t\t\t\t\t\t<int key=\"objectID\">351</int>\n\t\t\t\t\t\t<reference key=\"object\" ref=\"197661976\"/>\n\t\t\t\t\t\t<reference key=\"parent\" ref=\"698887838\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<object class=\"IBObjectRecord\">\n\t\t\t\t\t\t<int key=\"objectID\">354</int>\n\t\t\t\t\t\t<reference key=\"object\" ref=\"708854459\"/>\n\t\t\t\t\t\t<reference key=\"parent\" ref=\"698887838\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<object class=\"IBObjectRecord\">\n\t\t\t\t\t\t<int key=\"objectID\">371</int>\n\t\t\t\t\t\t<reference key=\"object\" ref=\"972006081\"/>\n\t\t\t\t\t\t<object class=\"NSMutableArray\" key=\"children\">\n\t\t\t\t\t\t\t<bool key=\"EncodedWithXMLCoder\">YES</bool>\n\t\t\t\t\t\t\t<reference ref=\"439893737\"/>\n\t\t\t\t\t\t</object>\n\t\t\t\t\t\t<reference key=\"parent\" ref=\"0\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<object class=\"IBObjectRecord\">\n\t\t\t\t\t\t<int key=\"objectID\">372</int>\n\t\t\t\t\t\t<reference key=\"object\" ref=\"439893737\"/>\n\t\t\t\t\t\t<object class=\"NSMutableArray\" key=\"children\">\n\t\t\t\t\t\t\t<bool key=\"EncodedWithXMLCoder\">YES</bool>\n\t\t\t\t\t\t\t<reference ref=\"765794976\"/>\n\t\t\t\t\t\t\t<reference ref=\"394479719\"/>\n\t\t\t\t\t\t\t<reference ref=\"327821739\"/>\n\t\t\t\t\t\t\t<reference ref=\"663855000\"/>\n\t\t\t\t\t\t\t<reference ref=\"783923701\"/>\n\t\t\t\t\t\t\t<reference ref=\"167731747\"/>\n\t\t\t\t\t\t\t<reference ref=\"161503078\"/>\n\t\t\t\t\t\t\t<reference ref=\"935404353\"/>\n\t\t\t\t\t\t\t<reference ref=\"264769268\"/>\n\t\t\t\t\t\t</object>\n\t\t\t\t\t\t<reference key=\"parent\" ref=\"972006081\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<object class=\"IBObjectRecord\">\n\t\t\t\t\t\t<int key=\"objectID\">375</int>\n\t\t\t\t\t\t<reference key=\"object\" ref=\"302598603\"/>\n\t\t\t\t\t\t<object class=\"NSMutableArray\" key=\"children\">\n\t\t\t\t\t\t\t<bool key=\"EncodedWithXMLCoder\">YES</bool>\n\t\t\t\t\t\t\t<reference ref=\"941447902\"/>\n\t\t\t\t\t\t</object>\n\t\t\t\t\t\t<reference key=\"parent\" ref=\"649796088\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<object class=\"IBObjectRecord\">\n\t\t\t\t\t\t<int key=\"objectID\">376</int>\n\t\t\t\t\t\t<reference key=\"object\" ref=\"941447902\"/>\n\t\t\t\t\t\t<object class=\"NSMutableArray\" key=\"children\">\n\t\t\t\t\t\t\t<bool key=\"EncodedWithXMLCoder\">YES</bool>\n\t\t\t\t\t\t\t<reference ref=\"792887677\"/>\n\t\t\t\t\t\t\t<reference ref=\"215659978\"/>\n\t\t\t\t\t\t</object>\n\t\t\t\t\t\t<reference key=\"parent\" ref=\"302598603\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<object class=\"IBObjectRecord\">\n\t\t\t\t\t\t<int key=\"objectID\">377</int>\n\t\t\t\t\t\t<reference key=\"object\" ref=\"792887677\"/>\n\t\t\t\t\t\t<object class=\"NSMutableArray\" key=\"children\">\n\t\t\t\t\t\t\t<bool key=\"EncodedWithXMLCoder\">YES</bool>\n\t\t\t\t\t\t\t<reference ref=\"786677654\"/>\n\t\t\t\t\t\t</object>\n\t\t\t\t\t\t<reference key=\"parent\" ref=\"941447902\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<object class=\"IBObjectRecord\">\n\t\t\t\t\t\t<int key=\"objectID\">388</int>\n\t\t\t\t\t\t<reference key=\"object\" ref=\"786677654\"/>\n\t\t\t\t\t\t<object class=\"NSMutableArray\" key=\"children\">\n\t\t\t\t\t\t\t<bool key=\"EncodedWithXMLCoder\">YES</bool>\n\t\t\t\t\t\t\t<reference ref=\"159677712\"/>\n\t\t\t\t\t\t\t<reference ref=\"305399458\"/>\n\t\t\t\t\t\t\t<reference ref=\"814362025\"/>\n\t\t\t\t\t\t\t<reference ref=\"330926929\"/>\n\t\t\t\t\t\t\t<reference ref=\"533507878\"/>\n\t\t\t\t\t\t\t<reference ref=\"158063935\"/>\n\t\t\t\t\t\t\t<reference ref=\"885547335\"/>\n\t\t\t\t\t\t\t<reference ref=\"901062459\"/>\n\t\t\t\t\t\t\t<reference ref=\"767671776\"/>\n\t\t\t\t\t\t\t<reference ref=\"691570813\"/>\n\t\t\t\t\t\t\t<reference ref=\"769124883\"/>\n\t\t\t\t\t\t\t<reference ref=\"739652853\"/>\n\t\t\t\t\t\t\t<reference ref=\"1012600125\"/>\n\t\t\t\t\t\t\t<reference ref=\"214559597\"/>\n\t\t\t\t\t\t\t<reference ref=\"596732606\"/>\n\t\t\t\t\t\t\t<reference ref=\"393423671\"/>\n\t\t\t\t\t\t</object>\n\t\t\t\t\t\t<reference key=\"parent\" ref=\"792887677\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<object class=\"IBObjectRecord\">\n\t\t\t\t\t\t<int key=\"objectID\">389</int>\n\t\t\t\t\t\t<reference key=\"object\" ref=\"159677712\"/>\n\t\t\t\t\t\t<reference key=\"parent\" ref=\"786677654\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<object class=\"IBObjectRecord\">\n\t\t\t\t\t\t<int key=\"objectID\">390</int>\n\t\t\t\t\t\t<reference key=\"object\" ref=\"305399458\"/>\n\t\t\t\t\t\t<reference key=\"parent\" ref=\"786677654\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<object class=\"IBObjectRecord\">\n\t\t\t\t\t\t<int key=\"objectID\">391</int>\n\t\t\t\t\t\t<reference key=\"object\" ref=\"814362025\"/>\n\t\t\t\t\t\t<reference key=\"parent\" ref=\"786677654\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<object class=\"IBObjectRecord\">\n\t\t\t\t\t\t<int key=\"objectID\">392</int>\n\t\t\t\t\t\t<reference key=\"object\" ref=\"330926929\"/>\n\t\t\t\t\t\t<reference key=\"parent\" ref=\"786677654\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<object class=\"IBObjectRecord\">\n\t\t\t\t\t\t<int key=\"objectID\">393</int>\n\t\t\t\t\t\t<reference key=\"object\" ref=\"533507878\"/>\n\t\t\t\t\t\t<reference key=\"parent\" ref=\"786677654\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<object class=\"IBObjectRecord\">\n\t\t\t\t\t\t<int key=\"objectID\">394</int>\n\t\t\t\t\t\t<reference key=\"object\" ref=\"158063935\"/>\n\t\t\t\t\t\t<reference key=\"parent\" ref=\"786677654\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<object class=\"IBObjectRecord\">\n\t\t\t\t\t\t<int key=\"objectID\">395</int>\n\t\t\t\t\t\t<reference key=\"object\" ref=\"885547335\"/>\n\t\t\t\t\t\t<reference key=\"parent\" ref=\"786677654\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<object class=\"IBObjectRecord\">\n\t\t\t\t\t\t<int key=\"objectID\">396</int>\n\t\t\t\t\t\t<reference key=\"object\" ref=\"901062459\"/>\n\t\t\t\t\t\t<reference key=\"parent\" ref=\"786677654\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<object class=\"IBObjectRecord\">\n\t\t\t\t\t\t<int key=\"objectID\">397</int>\n\t\t\t\t\t\t<reference key=\"object\" ref=\"767671776\"/>\n\t\t\t\t\t\t<object class=\"NSMutableArray\" key=\"children\">\n\t\t\t\t\t\t\t<bool key=\"EncodedWithXMLCoder\">YES</bool>\n\t\t\t\t\t\t\t<reference ref=\"175441468\"/>\n\t\t\t\t\t\t</object>\n\t\t\t\t\t\t<reference key=\"parent\" ref=\"786677654\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<object class=\"IBObjectRecord\">\n\t\t\t\t\t\t<int key=\"objectID\">398</int>\n\t\t\t\t\t\t<reference key=\"object\" ref=\"691570813\"/>\n\t\t\t\t\t\t<object class=\"NSMutableArray\" key=\"children\">\n\t\t\t\t\t\t\t<bool key=\"EncodedWithXMLCoder\">YES</bool>\n\t\t\t\t\t\t\t<reference ref=\"1058217995\"/>\n\t\t\t\t\t\t</object>\n\t\t\t\t\t\t<reference key=\"parent\" ref=\"786677654\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<object class=\"IBObjectRecord\">\n\t\t\t\t\t\t<int key=\"objectID\">399</int>\n\t\t\t\t\t\t<reference key=\"object\" ref=\"769124883\"/>\n\t\t\t\t\t\t<object class=\"NSMutableArray\" key=\"children\">\n\t\t\t\t\t\t\t<bool key=\"EncodedWithXMLCoder\">YES</bool>\n\t\t\t\t\t\t\t<reference ref=\"18263474\"/>\n\t\t\t\t\t\t</object>\n\t\t\t\t\t\t<reference key=\"parent\" ref=\"786677654\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<object class=\"IBObjectRecord\">\n\t\t\t\t\t\t<int key=\"objectID\">400</int>\n\t\t\t\t\t\t<reference key=\"object\" ref=\"739652853\"/>\n\t\t\t\t\t\t<reference key=\"parent\" ref=\"786677654\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<object class=\"IBObjectRecord\">\n\t\t\t\t\t\t<int key=\"objectID\">401</int>\n\t\t\t\t\t\t<reference key=\"object\" ref=\"1012600125\"/>\n\t\t\t\t\t\t<reference key=\"parent\" ref=\"786677654\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<object class=\"IBObjectRecord\">\n\t\t\t\t\t\t<int key=\"objectID\">402</int>\n\t\t\t\t\t\t<reference key=\"object\" ref=\"214559597\"/>\n\t\t\t\t\t\t<reference key=\"parent\" ref=\"786677654\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<object class=\"IBObjectRecord\">\n\t\t\t\t\t\t<int key=\"objectID\">403</int>\n\t\t\t\t\t\t<reference key=\"object\" ref=\"596732606\"/>\n\t\t\t\t\t\t<reference key=\"parent\" ref=\"786677654\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<object class=\"IBObjectRecord\">\n\t\t\t\t\t\t<int key=\"objectID\">404</int>\n\t\t\t\t\t\t<reference key=\"object\" ref=\"393423671\"/>\n\t\t\t\t\t\t<reference key=\"parent\" ref=\"786677654\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<object class=\"IBObjectRecord\">\n\t\t\t\t\t\t<int key=\"objectID\">405</int>\n\t\t\t\t\t\t<reference key=\"object\" ref=\"18263474\"/>\n\t\t\t\t\t\t<object class=\"NSMutableArray\" key=\"children\">\n\t\t\t\t\t\t\t<bool key=\"EncodedWithXMLCoder\">YES</bool>\n\t\t\t\t\t\t\t<reference ref=\"257962622\"/>\n\t\t\t\t\t\t\t<reference ref=\"644725453\"/>\n\t\t\t\t\t\t\t<reference ref=\"1037576581\"/>\n\t\t\t\t\t\t\t<reference ref=\"941806246\"/>\n\t\t\t\t\t\t\t<reference ref=\"1045724900\"/>\n\t\t\t\t\t\t</object>\n\t\t\t\t\t\t<reference key=\"parent\" ref=\"769124883\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<object class=\"IBObjectRecord\">\n\t\t\t\t\t\t<int key=\"objectID\">406</int>\n\t\t\t\t\t\t<reference key=\"object\" ref=\"257962622\"/>\n\t\t\t\t\t\t<reference key=\"parent\" ref=\"18263474\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<object class=\"IBObjectRecord\">\n\t\t\t\t\t\t<int key=\"objectID\">407</int>\n\t\t\t\t\t\t<reference key=\"object\" ref=\"644725453\"/>\n\t\t\t\t\t\t<reference key=\"parent\" ref=\"18263474\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<object class=\"IBObjectRecord\">\n\t\t\t\t\t\t<int key=\"objectID\">408</int>\n\t\t\t\t\t\t<reference key=\"object\" ref=\"1037576581\"/>\n\t\t\t\t\t\t<reference key=\"parent\" ref=\"18263474\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<object class=\"IBObjectRecord\">\n\t\t\t\t\t\t<int key=\"objectID\">409</int>\n\t\t\t\t\t\t<reference key=\"object\" ref=\"941806246\"/>\n\t\t\t\t\t\t<reference key=\"parent\" ref=\"18263474\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<object class=\"IBObjectRecord\">\n\t\t\t\t\t\t<int key=\"objectID\">410</int>\n\t\t\t\t\t\t<reference key=\"object\" ref=\"1045724900\"/>\n\t\t\t\t\t\t<reference key=\"parent\" ref=\"18263474\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<object class=\"IBObjectRecord\">\n\t\t\t\t\t\t<int key=\"objectID\">411</int>\n\t\t\t\t\t\t<reference key=\"object\" ref=\"1058217995\"/>\n\t\t\t\t\t\t<object class=\"NSMutableArray\" key=\"children\">\n\t\t\t\t\t\t\t<bool key=\"EncodedWithXMLCoder\">YES</bool>\n\t\t\t\t\t\t\t<reference ref=\"706297211\"/>\n\t\t\t\t\t\t\t<reference ref=\"568384683\"/>\n\t\t\t\t\t\t\t<reference ref=\"663508465\"/>\n\t\t\t\t\t\t</object>\n\t\t\t\t\t\t<reference key=\"parent\" ref=\"691570813\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<object class=\"IBObjectRecord\">\n\t\t\t\t\t\t<int key=\"objectID\">412</int>\n\t\t\t\t\t\t<reference key=\"object\" ref=\"706297211\"/>\n\t\t\t\t\t\t<reference key=\"parent\" ref=\"1058217995\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<object class=\"IBObjectRecord\">\n\t\t\t\t\t\t<int key=\"objectID\">413</int>\n\t\t\t\t\t\t<reference key=\"object\" ref=\"568384683\"/>\n\t\t\t\t\t\t<reference key=\"parent\" ref=\"1058217995\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<object class=\"IBObjectRecord\">\n\t\t\t\t\t\t<int key=\"objectID\">414</int>\n\t\t\t\t\t\t<reference key=\"object\" ref=\"663508465\"/>\n\t\t\t\t\t\t<reference key=\"parent\" ref=\"1058217995\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<object class=\"IBObjectRecord\">\n\t\t\t\t\t\t<int key=\"objectID\">415</int>\n\t\t\t\t\t\t<reference key=\"object\" ref=\"175441468\"/>\n\t\t\t\t\t\t<object class=\"NSMutableArray\" key=\"children\">\n\t\t\t\t\t\t\t<bool key=\"EncodedWithXMLCoder\">YES</bool>\n\t\t\t\t\t\t\t<reference ref=\"252969304\"/>\n\t\t\t\t\t\t\t<reference ref=\"766922938\"/>\n\t\t\t\t\t\t\t<reference ref=\"677519740\"/>\n\t\t\t\t\t\t\t<reference ref=\"238351151\"/>\n\t\t\t\t\t\t</object>\n\t\t\t\t\t\t<reference key=\"parent\" ref=\"767671776\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<object class=\"IBObjectRecord\">\n\t\t\t\t\t\t<int key=\"objectID\">416</int>\n\t\t\t\t\t\t<reference key=\"object\" ref=\"252969304\"/>\n\t\t\t\t\t\t<reference key=\"parent\" ref=\"175441468\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<object class=\"IBObjectRecord\">\n\t\t\t\t\t\t<int key=\"objectID\">417</int>\n\t\t\t\t\t\t<reference key=\"object\" ref=\"766922938\"/>\n\t\t\t\t\t\t<reference key=\"parent\" ref=\"175441468\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<object class=\"IBObjectRecord\">\n\t\t\t\t\t\t<int key=\"objectID\">418</int>\n\t\t\t\t\t\t<reference key=\"object\" ref=\"677519740\"/>\n\t\t\t\t\t\t<reference key=\"parent\" ref=\"175441468\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<object class=\"IBObjectRecord\">\n\t\t\t\t\t\t<int key=\"objectID\">419</int>\n\t\t\t\t\t\t<reference key=\"object\" ref=\"238351151\"/>\n\t\t\t\t\t\t<reference key=\"parent\" ref=\"175441468\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<object class=\"IBObjectRecord\">\n\t\t\t\t\t\t<int key=\"objectID\">420</int>\n\t\t\t\t\t\t<reference key=\"object\" ref=\"755631768\"/>\n\t\t\t\t\t\t<reference key=\"parent\" ref=\"0\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<object class=\"IBObjectRecord\">\n\t\t\t\t\t\t<int key=\"objectID\">450</int>\n\t\t\t\t\t\t<reference key=\"object\" ref=\"288088188\"/>\n\t\t\t\t\t\t<object class=\"NSMutableArray\" key=\"children\">\n\t\t\t\t\t\t\t<bool key=\"EncodedWithXMLCoder\">YES</bool>\n\t\t\t\t\t\t\t<reference ref=\"579392910\"/>\n\t\t\t\t\t\t</object>\n\t\t\t\t\t\t<reference key=\"parent\" ref=\"789758025\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<object class=\"IBObjectRecord\">\n\t\t\t\t\t\t<int key=\"objectID\">451</int>\n\t\t\t\t\t\t<reference key=\"object\" ref=\"579392910\"/>\n\t\t\t\t\t\t<object class=\"NSMutableArray\" key=\"children\">\n\t\t\t\t\t\t\t<bool key=\"EncodedWithXMLCoder\">YES</bool>\n\t\t\t\t\t\t\t<reference ref=\"1060694897\"/>\n\t\t\t\t\t\t\t<reference ref=\"879586729\"/>\n\t\t\t\t\t\t\t<reference ref=\"56570060\"/>\n\t\t\t\t\t\t</object>\n\t\t\t\t\t\t<reference key=\"parent\" ref=\"288088188\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<object class=\"IBObjectRecord\">\n\t\t\t\t\t\t<int key=\"objectID\">452</int>\n\t\t\t\t\t\t<reference key=\"object\" ref=\"1060694897\"/>\n\t\t\t\t\t\t<reference key=\"parent\" ref=\"579392910\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<object class=\"IBObjectRecord\">\n\t\t\t\t\t\t<int key=\"objectID\">453</int>\n\t\t\t\t\t\t<reference key=\"object\" ref=\"859480356\"/>\n\t\t\t\t\t\t<reference key=\"parent\" ref=\"769623530\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<object class=\"IBObjectRecord\">\n\t\t\t\t\t\t<int key=\"objectID\">454</int>\n\t\t\t\t\t\t<reference key=\"object\" ref=\"795346622\"/>\n\t\t\t\t\t\t<reference key=\"parent\" ref=\"769623530\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<object class=\"IBObjectRecord\">\n\t\t\t\t\t\t<int key=\"objectID\">457</int>\n\t\t\t\t\t\t<reference key=\"object\" ref=\"65139061\"/>\n\t\t\t\t\t\t<reference key=\"parent\" ref=\"698887838\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<object class=\"IBObjectRecord\">\n\t\t\t\t\t\t<int key=\"objectID\">459</int>\n\t\t\t\t\t\t<reference key=\"object\" ref=\"19036812\"/>\n\t\t\t\t\t\t<reference key=\"parent\" ref=\"698887838\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<object class=\"IBObjectRecord\">\n\t\t\t\t\t\t<int key=\"objectID\">460</int>\n\t\t\t\t\t\t<reference key=\"object\" ref=\"672708820\"/>\n\t\t\t\t\t\t<reference key=\"parent\" ref=\"698887838\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<object class=\"IBObjectRecord\">\n\t\t\t\t\t\t<int key=\"objectID\">462</int>\n\t\t\t\t\t\t<reference key=\"object\" ref=\"537092702\"/>\n\t\t\t\t\t\t<reference key=\"parent\" ref=\"698887838\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<object class=\"IBObjectRecord\">\n\t\t\t\t\t\t<int key=\"objectID\">465</int>\n\t\t\t\t\t\t<reference key=\"object\" ref=\"879586729\"/>\n\t\t\t\t\t\t<reference key=\"parent\" ref=\"579392910\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<object class=\"IBObjectRecord\">\n\t\t\t\t\t\t<int key=\"objectID\">466</int>\n\t\t\t\t\t\t<reference key=\"object\" ref=\"56570060\"/>\n\t\t\t\t\t\t<reference key=\"parent\" ref=\"579392910\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<object class=\"IBObjectRecord\">\n\t\t\t\t\t\t<int key=\"objectID\">485</int>\n\t\t\t\t\t\t<reference key=\"object\" ref=\"82994268\"/>\n\t\t\t\t\t\t<reference key=\"parent\" ref=\"789758025\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<object class=\"IBObjectRecord\">\n\t\t\t\t\t\t<int key=\"objectID\">490</int>\n\t\t\t\t\t\t<reference key=\"object\" ref=\"448692316\"/>\n\t\t\t\t\t\t<object class=\"NSMutableArray\" key=\"children\">\n\t\t\t\t\t\t\t<bool key=\"EncodedWithXMLCoder\">YES</bool>\n\t\t\t\t\t\t\t<reference ref=\"992780483\"/>\n\t\t\t\t\t\t</object>\n\t\t\t\t\t\t<reference key=\"parent\" ref=\"649796088\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<object class=\"IBObjectRecord\">\n\t\t\t\t\t\t<int key=\"objectID\">491</int>\n\t\t\t\t\t\t<reference key=\"object\" ref=\"992780483\"/>\n\t\t\t\t\t\t<object class=\"NSMutableArray\" key=\"children\">\n\t\t\t\t\t\t\t<bool key=\"EncodedWithXMLCoder\">YES</bool>\n\t\t\t\t\t\t\t<reference ref=\"105068016\"/>\n\t\t\t\t\t\t</object>\n\t\t\t\t\t\t<reference key=\"parent\" ref=\"448692316\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<object class=\"IBObjectRecord\">\n\t\t\t\t\t\t<int key=\"objectID\">492</int>\n\t\t\t\t\t\t<reference key=\"object\" ref=\"105068016\"/>\n\t\t\t\t\t\t<reference key=\"parent\" ref=\"992780483\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<object class=\"IBObjectRecord\">\n\t\t\t\t\t\t<int key=\"objectID\">494</int>\n\t\t\t\t\t\t<reference key=\"object\" ref=\"976324537\"/>\n\t\t\t\t\t\t<reference key=\"parent\" ref=\"0\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<object class=\"IBObjectRecord\">\n\t\t\t\t\t\t<int key=\"objectID\">496</int>\n\t\t\t\t\t\t<reference key=\"object\" ref=\"215659978\"/>\n\t\t\t\t\t\t<object class=\"NSMutableArray\" key=\"children\">\n\t\t\t\t\t\t\t<bool key=\"EncodedWithXMLCoder\">YES</bool>\n\t\t\t\t\t\t\t<reference ref=\"446991534\"/>\n\t\t\t\t\t\t</object>\n\t\t\t\t\t\t<reference key=\"parent\" ref=\"941447902\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<object class=\"IBObjectRecord\">\n\t\t\t\t\t\t<int key=\"objectID\">497</int>\n\t\t\t\t\t\t<reference key=\"object\" ref=\"446991534\"/>\n\t\t\t\t\t\t<object class=\"NSMutableArray\" key=\"children\">\n\t\t\t\t\t\t\t<bool key=\"EncodedWithXMLCoder\">YES</bool>\n\t\t\t\t\t\t\t<reference ref=\"875092757\"/>\n\t\t\t\t\t\t\t<reference ref=\"630155264\"/>\n\t\t\t\t\t\t\t<reference ref=\"945678886\"/>\n\t\t\t\t\t\t\t<reference ref=\"512868991\"/>\n\t\t\t\t\t\t\t<reference ref=\"163117631\"/>\n\t\t\t\t\t\t\t<reference ref=\"31516759\"/>\n\t\t\t\t\t\t\t<reference ref=\"908105787\"/>\n\t\t\t\t\t\t\t<reference ref=\"644046920\"/>\n\t\t\t\t\t\t\t<reference ref=\"231811626\"/>\n\t\t\t\t\t\t\t<reference ref=\"883618387\"/>\n\t\t\t\t\t\t</object>\n\t\t\t\t\t\t<reference key=\"parent\" ref=\"215659978\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<object class=\"IBObjectRecord\">\n\t\t\t\t\t\t<int key=\"objectID\">498</int>\n\t\t\t\t\t\t<reference key=\"object\" ref=\"875092757\"/>\n\t\t\t\t\t\t<reference key=\"parent\" ref=\"446991534\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<object class=\"IBObjectRecord\">\n\t\t\t\t\t\t<int key=\"objectID\">499</int>\n\t\t\t\t\t\t<reference key=\"object\" ref=\"630155264\"/>\n\t\t\t\t\t\t<reference key=\"parent\" ref=\"446991534\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<object class=\"IBObjectRecord\">\n\t\t\t\t\t\t<int key=\"objectID\">500</int>\n\t\t\t\t\t\t<reference key=\"object\" ref=\"945678886\"/>\n\t\t\t\t\t\t<reference key=\"parent\" ref=\"446991534\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<object class=\"IBObjectRecord\">\n\t\t\t\t\t\t<int key=\"objectID\">501</int>\n\t\t\t\t\t\t<reference key=\"object\" ref=\"512868991\"/>\n\t\t\t\t\t\t<reference key=\"parent\" ref=\"446991534\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<object class=\"IBObjectRecord\">\n\t\t\t\t\t\t<int key=\"objectID\">502</int>\n\t\t\t\t\t\t<reference key=\"object\" ref=\"163117631\"/>\n\t\t\t\t\t\t<reference key=\"parent\" ref=\"446991534\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<object class=\"IBObjectRecord\">\n\t\t\t\t\t\t<int key=\"objectID\">503</int>\n\t\t\t\t\t\t<reference key=\"object\" ref=\"31516759\"/>\n\t\t\t\t\t\t<object class=\"NSMutableArray\" key=\"children\">\n\t\t\t\t\t\t\t<bool key=\"EncodedWithXMLCoder\">YES</bool>\n\t\t\t\t\t\t\t<reference ref=\"956096989\"/>\n\t\t\t\t\t\t</object>\n\t\t\t\t\t\t<reference key=\"parent\" ref=\"446991534\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<object class=\"IBObjectRecord\">\n\t\t\t\t\t\t<int key=\"objectID\">504</int>\n\t\t\t\t\t\t<reference key=\"object\" ref=\"908105787\"/>\n\t\t\t\t\t\t<reference key=\"parent\" ref=\"446991534\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<object class=\"IBObjectRecord\">\n\t\t\t\t\t\t<int key=\"objectID\">505</int>\n\t\t\t\t\t\t<reference key=\"object\" ref=\"644046920\"/>\n\t\t\t\t\t\t<reference key=\"parent\" ref=\"446991534\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<object class=\"IBObjectRecord\">\n\t\t\t\t\t\t<int key=\"objectID\">506</int>\n\t\t\t\t\t\t<reference key=\"object\" ref=\"231811626\"/>\n\t\t\t\t\t\t<reference key=\"parent\" ref=\"446991534\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<object class=\"IBObjectRecord\">\n\t\t\t\t\t\t<int key=\"objectID\">507</int>\n\t\t\t\t\t\t<reference key=\"object\" ref=\"883618387\"/>\n\t\t\t\t\t\t<reference key=\"parent\" ref=\"446991534\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<object class=\"IBObjectRecord\">\n\t\t\t\t\t\t<int key=\"objectID\">508</int>\n\t\t\t\t\t\t<reference key=\"object\" ref=\"956096989\"/>\n\t\t\t\t\t\t<object class=\"NSMutableArray\" key=\"children\">\n\t\t\t\t\t\t\t<bool key=\"EncodedWithXMLCoder\">YES</bool>\n\t\t\t\t\t\t\t<reference ref=\"257099033\"/>\n\t\t\t\t\t\t\t<reference ref=\"551969625\"/>\n\t\t\t\t\t\t\t<reference ref=\"249532473\"/>\n\t\t\t\t\t\t\t<reference ref=\"607364498\"/>\n\t\t\t\t\t\t\t<reference ref=\"508151438\"/>\n\t\t\t\t\t\t\t<reference ref=\"981751889\"/>\n\t\t\t\t\t\t\t<reference ref=\"380031999\"/>\n\t\t\t\t\t\t\t<reference ref=\"825984362\"/>\n\t\t\t\t\t\t\t<reference ref=\"560145579\"/>\n\t\t\t\t\t\t</object>\n\t\t\t\t\t\t<reference key=\"parent\" ref=\"31516759\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<object class=\"IBObjectRecord\">\n\t\t\t\t\t\t<int key=\"objectID\">509</int>\n\t\t\t\t\t\t<reference key=\"object\" ref=\"257099033\"/>\n\t\t\t\t\t\t<reference key=\"parent\" ref=\"956096989\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<object class=\"IBObjectRecord\">\n\t\t\t\t\t\t<int key=\"objectID\">510</int>\n\t\t\t\t\t\t<reference key=\"object\" ref=\"551969625\"/>\n\t\t\t\t\t\t<reference key=\"parent\" ref=\"956096989\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<object class=\"IBObjectRecord\">\n\t\t\t\t\t\t<int key=\"objectID\">511</int>\n\t\t\t\t\t\t<reference key=\"object\" ref=\"249532473\"/>\n\t\t\t\t\t\t<reference key=\"parent\" ref=\"956096989\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<object class=\"IBObjectRecord\">\n\t\t\t\t\t\t<int key=\"objectID\">512</int>\n\t\t\t\t\t\t<reference key=\"object\" ref=\"607364498\"/>\n\t\t\t\t\t\t<reference key=\"parent\" ref=\"956096989\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<object class=\"IBObjectRecord\">\n\t\t\t\t\t\t<int key=\"objectID\">513</int>\n\t\t\t\t\t\t<reference key=\"object\" ref=\"508151438\"/>\n\t\t\t\t\t\t<reference key=\"parent\" ref=\"956096989\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<object class=\"IBObjectRecord\">\n\t\t\t\t\t\t<int key=\"objectID\">514</int>\n\t\t\t\t\t\t<reference key=\"object\" ref=\"981751889\"/>\n\t\t\t\t\t\t<reference key=\"parent\" ref=\"956096989\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<object class=\"IBObjectRecord\">\n\t\t\t\t\t\t<int key=\"objectID\">515</int>\n\t\t\t\t\t\t<reference key=\"object\" ref=\"380031999\"/>\n\t\t\t\t\t\t<reference key=\"parent\" ref=\"956096989\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<object class=\"IBObjectRecord\">\n\t\t\t\t\t\t<int key=\"objectID\">516</int>\n\t\t\t\t\t\t<reference key=\"object\" ref=\"825984362\"/>\n\t\t\t\t\t\t<reference key=\"parent\" ref=\"956096989\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<object class=\"IBObjectRecord\">\n\t\t\t\t\t\t<int key=\"objectID\">517</int>\n\t\t\t\t\t\t<reference key=\"object\" ref=\"560145579\"/>\n\t\t\t\t\t\t<reference key=\"parent\" ref=\"956096989\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<object class=\"IBObjectRecord\">\n\t\t\t\t\t\t<int key=\"objectID\">533</int>\n\t\t\t\t\t\t<reference key=\"object\" ref=\"765794976\"/>\n\t\t\t\t\t\t<object class=\"NSMutableArray\" key=\"children\">\n\t\t\t\t\t\t\t<bool key=\"EncodedWithXMLCoder\">YES</bool>\n\t\t\t\t\t\t\t<reference ref=\"579012641\"/>\n\t\t\t\t\t\t</object>\n\t\t\t\t\t\t<reference key=\"parent\" ref=\"439893737\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<object class=\"IBObjectRecord\">\n\t\t\t\t\t\t<int key=\"objectID\">534</int>\n\t\t\t\t\t\t<reference key=\"object\" ref=\"579012641\"/>\n\t\t\t\t\t\t<reference key=\"parent\" ref=\"765794976\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<object class=\"IBObjectRecord\">\n\t\t\t\t\t\t<int key=\"objectID\">535</int>\n\t\t\t\t\t\t<reference key=\"object\" ref=\"394479719\"/>\n\t\t\t\t\t\t<object class=\"NSMutableArray\" key=\"children\">\n\t\t\t\t\t\t\t<bool key=\"EncodedWithXMLCoder\">YES</bool>\n\t\t\t\t\t\t\t<reference ref=\"16471822\"/>\n\t\t\t\t\t\t</object>\n\t\t\t\t\t\t<reference key=\"parent\" ref=\"439893737\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<object class=\"IBObjectRecord\">\n\t\t\t\t\t\t<int key=\"objectID\">536</int>\n\t\t\t\t\t\t<reference key=\"object\" ref=\"16471822\"/>\n\t\t\t\t\t\t<reference key=\"parent\" ref=\"394479719\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<object class=\"IBObjectRecord\">\n\t\t\t\t\t\t<int key=\"objectID\">537</int>\n\t\t\t\t\t\t<reference key=\"object\" ref=\"327821739\"/>\n\t\t\t\t\t\t<object class=\"NSMutableArray\" key=\"children\">\n\t\t\t\t\t\t\t<bool key=\"EncodedWithXMLCoder\">YES</bool>\n\t\t\t\t\t\t\t<reference ref=\"122895619\"/>\n\t\t\t\t\t\t</object>\n\t\t\t\t\t\t<reference key=\"parent\" ref=\"439893737\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<object class=\"IBObjectRecord\">\n\t\t\t\t\t\t<int key=\"objectID\">538</int>\n\t\t\t\t\t\t<reference key=\"object\" ref=\"122895619\"/>\n\t\t\t\t\t\t<reference key=\"parent\" ref=\"327821739\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<object class=\"IBObjectRecord\">\n\t\t\t\t\t\t<int key=\"objectID\">542</int>\n\t\t\t\t\t\t<reference key=\"object\" ref=\"167731747\"/>\n\t\t\t\t\t\t<object class=\"NSMutableArray\" key=\"children\">\n\t\t\t\t\t\t\t<bool key=\"EncodedWithXMLCoder\">YES</bool>\n\t\t\t\t\t\t\t<reference ref=\"855023043\"/>\n\t\t\t\t\t\t</object>\n\t\t\t\t\t\t<reference key=\"parent\" ref=\"439893737\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<object class=\"IBObjectRecord\">\n\t\t\t\t\t\t<int key=\"objectID\">543</int>\n\t\t\t\t\t\t<reference key=\"object\" ref=\"855023043\"/>\n\t\t\t\t\t\t<reference key=\"parent\" ref=\"167731747\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<object class=\"IBObjectRecord\">\n\t\t\t\t\t\t<int key=\"objectID\">545</int>\n\t\t\t\t\t\t<reference key=\"object\" ref=\"1007787480\"/>\n\t\t\t\t\t\t<reference key=\"parent\" ref=\"0\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<object class=\"IBObjectRecord\">\n\t\t\t\t\t\t<int key=\"objectID\">550</int>\n\t\t\t\t\t\t<reference key=\"object\" ref=\"935404353\"/>\n\t\t\t\t\t\t<object class=\"NSMutableArray\" key=\"children\">\n\t\t\t\t\t\t\t<bool key=\"EncodedWithXMLCoder\">YES</bool>\n\t\t\t\t\t\t\t<reference ref=\"785091278\"/>\n\t\t\t\t\t\t</object>\n\t\t\t\t\t\t<reference key=\"parent\" ref=\"439893737\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<object class=\"IBObjectRecord\">\n\t\t\t\t\t\t<int key=\"objectID\">551</int>\n\t\t\t\t\t\t<reference key=\"object\" ref=\"785091278\"/>\n\t\t\t\t\t\t<reference key=\"parent\" ref=\"935404353\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<object class=\"IBObjectRecord\">\n\t\t\t\t\t\t<int key=\"objectID\">552</int>\n\t\t\t\t\t\t<reference key=\"object\" ref=\"264769268\"/>\n\t\t\t\t\t\t<object class=\"NSMutableArray\" key=\"children\">\n\t\t\t\t\t\t\t<bool key=\"EncodedWithXMLCoder\">YES</bool>\n\t\t\t\t\t\t\t<reference ref=\"516108178\"/>\n\t\t\t\t\t\t</object>\n\t\t\t\t\t\t<reference key=\"parent\" ref=\"439893737\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<object class=\"IBObjectRecord\">\n\t\t\t\t\t\t<int key=\"objectID\">553</int>\n\t\t\t\t\t\t<reference key=\"object\" ref=\"516108178\"/>\n\t\t\t\t\t\t<reference key=\"parent\" ref=\"264769268\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<object class=\"IBObjectRecord\">\n\t\t\t\t\t\t<int key=\"objectID\">557</int>\n\t\t\t\t\t\t<reference key=\"object\" ref=\"663855000\"/>\n\t\t\t\t\t\t<object class=\"NSMutableArray\" key=\"children\">\n\t\t\t\t\t\t\t<bool key=\"EncodedWithXMLCoder\">YES</bool>\n\t\t\t\t\t\t\t<reference ref=\"400581401\"/>\n\t\t\t\t\t\t</object>\n\t\t\t\t\t\t<reference key=\"parent\" ref=\"439893737\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<object class=\"IBObjectRecord\">\n\t\t\t\t\t\t<int key=\"objectID\">558</int>\n\t\t\t\t\t\t<reference key=\"object\" ref=\"400581401\"/>\n\t\t\t\t\t\t<reference key=\"parent\" ref=\"663855000\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<object class=\"IBObjectRecord\">\n\t\t\t\t\t\t<int key=\"objectID\">559</int>\n\t\t\t\t\t\t<reference key=\"object\" ref=\"783923701\"/>\n\t\t\t\t\t\t<object class=\"NSMutableArray\" key=\"children\">\n\t\t\t\t\t\t\t<bool key=\"EncodedWithXMLCoder\">YES</bool>\n\t\t\t\t\t\t\t<reference ref=\"78164212\"/>\n\t\t\t\t\t\t</object>\n\t\t\t\t\t\t<reference key=\"parent\" ref=\"439893737\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<object class=\"IBObjectRecord\">\n\t\t\t\t\t\t<int key=\"objectID\">560</int>\n\t\t\t\t\t\t<reference key=\"object\" ref=\"78164212\"/>\n\t\t\t\t\t\t<reference key=\"parent\" ref=\"783923701\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<object class=\"IBObjectRecord\">\n\t\t\t\t\t\t<int key=\"objectID\">561</int>\n\t\t\t\t\t\t<reference key=\"object\" ref=\"161503078\"/>\n\t\t\t\t\t\t<object class=\"NSMutableArray\" key=\"children\">\n\t\t\t\t\t\t\t<bool key=\"EncodedWithXMLCoder\">YES</bool>\n\t\t\t\t\t\t\t<reference ref=\"1040653779\"/>\n\t\t\t\t\t\t</object>\n\t\t\t\t\t\t<reference key=\"parent\" ref=\"439893737\"/>\n\t\t\t\t\t</object>\n\t\t\t\t\t<object class=\"IBObjectRecord\">\n\t\t\t\t\t\t<int key=\"objectID\">562</int>\n\t\t\t\t\t\t<reference key=\"object\" ref=\"1040653779\"/>\n\t\t\t\t\t\t<reference key=\"parent\" ref=\"161503078\"/>\n\t\t\t\t\t</object>\n\t\t\t\t</object>\n\t\t\t</object>\n\t\t\t<object class=\"NSMutableDictionary\" key=\"flattenedProperties\">\n\t\t\t\t<bool key=\"EncodedWithXMLCoder\">YES</bool>\n\t\t\t\t<object class=\"NSArray\" key=\"dict.sortedKeys\">\n\t\t\t\t\t<bool key=\"EncodedWithXMLCoder\">YES</bool>\n\t\t\t\t\t<string>-3.IBPluginDependency</string>\n\t\t\t\t\t<string>112.IBPluginDependency</string>\n\t\t\t\t\t<string>112.ImportedFromIB2</string>\n\t\t\t\t\t<string>124.IBPluginDependency</string>\n\t\t\t\t\t<string>124.ImportedFromIB2</string>\n\t\t\t\t\t<string>125.IBPluginDependency</string>\n\t\t\t\t\t<string>125.ImportedFromIB2</string>\n\t\t\t\t\t<string>125.editorWindowContentRectSynchronizationRect</string>\n\t\t\t\t\t<string>126.IBPluginDependency</string>\n\t\t\t\t\t<string>126.ImportedFromIB2</string>\n\t\t\t\t\t<string>129.IBPluginDependency</string>\n\t\t\t\t\t<string>129.ImportedFromIB2</string>\n\t\t\t\t\t<string>130.IBPluginDependency</string>\n\t\t\t\t\t<string>130.ImportedFromIB2</string>\n\t\t\t\t\t<string>130.editorWindowContentRectSynchronizationRect</string>\n\t\t\t\t\t<string>131.IBPluginDependency</string>\n\t\t\t\t\t<string>131.ImportedFromIB2</string>\n\t\t\t\t\t<string>134.IBPluginDependency</string>\n\t\t\t\t\t<string>134.ImportedFromIB2</string>\n\t\t\t\t\t<string>136.IBPluginDependency</string>\n\t\t\t\t\t<string>136.ImportedFromIB2</string>\n\t\t\t\t\t<string>143.IBPluginDependency</string>\n\t\t\t\t\t<string>143.ImportedFromIB2</string>\n\t\t\t\t\t<string>144.IBPluginDependency</string>\n\t\t\t\t\t<string>144.ImportedFromIB2</string>\n\t\t\t\t\t<string>145.IBPluginDependency</string>\n\t\t\t\t\t<string>145.ImportedFromIB2</string>\n\t\t\t\t\t<string>149.IBPluginDependency</string>\n\t\t\t\t\t<string>149.ImportedFromIB2</string>\n\t\t\t\t\t<string>150.IBPluginDependency</string>\n\t\t\t\t\t<string>150.ImportedFromIB2</string>\n\t\t\t\t\t<string>19.IBPluginDependency</string>\n\t\t\t\t\t<string>19.ImportedFromIB2</string>\n\t\t\t\t\t<string>195.IBPluginDependency</string>\n\t\t\t\t\t<string>195.ImportedFromIB2</string>\n\t\t\t\t\t<string>196.IBPluginDependency</string>\n\t\t\t\t\t<string>196.ImportedFromIB2</string>\n\t\t\t\t\t<string>197.IBPluginDependency</string>\n\t\t\t\t\t<string>197.ImportedFromIB2</string>\n\t\t\t\t\t<string>198.IBPluginDependency</string>\n\t\t\t\t\t<string>198.ImportedFromIB2</string>\n\t\t\t\t\t<string>199.IBPluginDependency</string>\n\t\t\t\t\t<string>199.ImportedFromIB2</string>\n\t\t\t\t\t<string>200.IBEditorWindowLastContentRect</string>\n\t\t\t\t\t<string>200.IBPluginDependency</string>\n\t\t\t\t\t<string>200.ImportedFromIB2</string>\n\t\t\t\t\t<string>200.editorWindowContentRectSynchronizationRect</string>\n\t\t\t\t\t<string>201.IBPluginDependency</string>\n\t\t\t\t\t<string>201.ImportedFromIB2</string>\n\t\t\t\t\t<string>202.IBPluginDependency</string>\n\t\t\t\t\t<string>202.ImportedFromIB2</string>\n\t\t\t\t\t<string>203.IBPluginDependency</string>\n\t\t\t\t\t<string>203.ImportedFromIB2</string>\n\t\t\t\t\t<string>204.IBPluginDependency</string>\n\t\t\t\t\t<string>204.ImportedFromIB2</string>\n\t\t\t\t\t<string>205.IBEditorWindowLastContentRect</string>\n\t\t\t\t\t<string>205.IBPluginDependency</string>\n\t\t\t\t\t<string>205.ImportedFromIB2</string>\n\t\t\t\t\t<string>205.editorWindowContentRectSynchronizationRect</string>\n\t\t\t\t\t<string>206.IBPluginDependency</string>\n\t\t\t\t\t<string>206.ImportedFromIB2</string>\n\t\t\t\t\t<string>207.IBPluginDependency</string>\n\t\t\t\t\t<string>207.ImportedFromIB2</string>\n\t\t\t\t\t<string>208.IBPluginDependency</string>\n\t\t\t\t\t<string>208.ImportedFromIB2</string>\n\t\t\t\t\t<string>209.IBPluginDependency</string>\n\t\t\t\t\t<string>209.ImportedFromIB2</string>\n\t\t\t\t\t<string>210.IBPluginDependency</string>\n\t\t\t\t\t<string>210.ImportedFromIB2</string>\n\t\t\t\t\t<string>211.IBPluginDependency</string>\n\t\t\t\t\t<string>211.ImportedFromIB2</string>\n\t\t\t\t\t<string>212.IBPluginDependency</string>\n\t\t\t\t\t<string>212.ImportedFromIB2</string>\n\t\t\t\t\t<string>212.editorWindowContentRectSynchronizationRect</string>\n\t\t\t\t\t<string>213.IBPluginDependency</string>\n\t\t\t\t\t<string>213.ImportedFromIB2</string>\n\t\t\t\t\t<string>214.IBPluginDependency</string>\n\t\t\t\t\t<string>214.ImportedFromIB2</string>\n\t\t\t\t\t<string>215.IBPluginDependency</string>\n\t\t\t\t\t<string>215.ImportedFromIB2</string>\n\t\t\t\t\t<string>216.IBPluginDependency</string>\n\t\t\t\t\t<string>216.ImportedFromIB2</string>\n\t\t\t\t\t<string>217.IBPluginDependency</string>\n\t\t\t\t\t<string>217.ImportedFromIB2</string>\n\t\t\t\t\t<string>218.IBPluginDependency</string>\n\t\t\t\t\t<string>218.ImportedFromIB2</string>\n\t\t\t\t\t<string>219.IBPluginDependency</string>\n\t\t\t\t\t<string>219.ImportedFromIB2</string>\n\t\t\t\t\t<string>220.IBEditorWindowLastContentRect</string>\n\t\t\t\t\t<string>220.IBPluginDependency</string>\n\t\t\t\t\t<string>220.ImportedFromIB2</string>\n\t\t\t\t\t<string>220.editorWindowContentRectSynchronizationRect</string>\n\t\t\t\t\t<string>221.IBPluginDependency</string>\n\t\t\t\t\t<string>221.ImportedFromIB2</string>\n\t\t\t\t\t<string>23.IBPluginDependency</string>\n\t\t\t\t\t<string>23.ImportedFromIB2</string>\n\t\t\t\t\t<string>236.IBPluginDependency</string>\n\t\t\t\t\t<string>236.ImportedFromIB2</string>\n\t\t\t\t\t<string>239.IBPluginDependency</string>\n\t\t\t\t\t<string>239.ImportedFromIB2</string>\n\t\t\t\t\t<string>24.IBEditorWindowLastContentRect</string>\n\t\t\t\t\t<string>24.IBPluginDependency</string>\n\t\t\t\t\t<string>24.ImportedFromIB2</string>\n\t\t\t\t\t<string>24.editorWindowContentRectSynchronizationRect</string>\n\t\t\t\t\t<string>29.IBEditorWindowLastContentRect</string>\n\t\t\t\t\t<string>29.IBPluginDependency</string>\n\t\t\t\t\t<string>29.ImportedFromIB2</string>\n\t\t\t\t\t<string>29.WindowOrigin</string>\n\t\t\t\t\t<string>29.editorWindowContentRectSynchronizationRect</string>\n\t\t\t\t\t<string>295.IBPluginDependency</string>\n\t\t\t\t\t<string>296.IBEditorWindowLastContentRect</string>\n\t\t\t\t\t<string>296.IBPluginDependency</string>\n\t\t\t\t\t<string>296.editorWindowContentRectSynchronizationRect</string>\n\t\t\t\t\t<string>297.IBPluginDependency</string>\n\t\t\t\t\t<string>298.IBPluginDependency</string>\n\t\t\t\t\t<string>346.IBPluginDependency</string>\n\t\t\t\t\t<string>346.ImportedFromIB2</string>\n\t\t\t\t\t<string>348.IBPluginDependency</string>\n\t\t\t\t\t<string>348.ImportedFromIB2</string>\n\t\t\t\t\t<string>349.IBEditorWindowLastContentRect</string>\n\t\t\t\t\t<string>349.IBPluginDependency</string>\n\t\t\t\t\t<string>349.ImportedFromIB2</string>\n\t\t\t\t\t<string>349.editorWindowContentRectSynchronizationRect</string>\n\t\t\t\t\t<string>350.IBPluginDependency</string>\n\t\t\t\t\t<string>350.ImportedFromIB2</string>\n\t\t\t\t\t<string>351.IBPluginDependency</string>\n\t\t\t\t\t<string>351.ImportedFromIB2</string>\n\t\t\t\t\t<string>354.IBPluginDependency</string>\n\t\t\t\t\t<string>354.ImportedFromIB2</string>\n\t\t\t\t\t<string>371.IBEditorWindowLastContentRect</string>\n\t\t\t\t\t<string>371.IBPluginDependency</string>\n\t\t\t\t\t<string>371.IBWindowTemplateEditedContentRect</string>\n\t\t\t\t\t<string>371.NSWindowTemplate.visibleAtLaunch</string>\n\t\t\t\t\t<string>371.editorWindowContentRectSynchronizationRect</string>\n\t\t\t\t\t<string>371.windowTemplate.hasMaxSize</string>\n\t\t\t\t\t<string>371.windowTemplate.maxSize</string>\n\t\t\t\t\t<string>372.IBPluginDependency</string>\n\t\t\t\t\t<string>375.IBPluginDependency</string>\n\t\t\t\t\t<string>376.IBEditorWindowLastContentRect</string>\n\t\t\t\t\t<string>376.IBPluginDependency</string>\n\t\t\t\t\t<string>377.IBPluginDependency</string>\n\t\t\t\t\t<string>388.IBEditorWindowLastContentRect</string>\n\t\t\t\t\t<string>388.IBPluginDependency</string>\n\t\t\t\t\t<string>389.IBPluginDependency</string>\n\t\t\t\t\t<string>390.IBPluginDependency</string>\n\t\t\t\t\t<string>391.IBPluginDependency</string>\n\t\t\t\t\t<string>392.IBPluginDependency</string>\n\t\t\t\t\t<string>393.IBPluginDependency</string>\n\t\t\t\t\t<string>394.IBPluginDependency</string>\n\t\t\t\t\t<string>395.IBPluginDependency</string>\n\t\t\t\t\t<string>396.IBPluginDependency</string>\n\t\t\t\t\t<string>397.IBPluginDependency</string>\n\t\t\t\t\t<string>398.IBPluginDependency</string>\n\t\t\t\t\t<string>399.IBPluginDependency</string>\n\t\t\t\t\t<string>400.IBPluginDependency</string>\n\t\t\t\t\t<string>401.IBPluginDependency</string>\n\t\t\t\t\t<string>402.IBPluginDependency</string>\n\t\t\t\t\t<string>403.IBPluginDependency</string>\n\t\t\t\t\t<string>404.IBPluginDependency</string>\n\t\t\t\t\t<string>405.IBPluginDependency</string>\n\t\t\t\t\t<string>406.IBPluginDependency</string>\n\t\t\t\t\t<string>407.IBPluginDependency</string>\n\t\t\t\t\t<string>408.IBPluginDependency</string>\n\t\t\t\t\t<string>409.IBPluginDependency</string>\n\t\t\t\t\t<string>410.IBPluginDependency</string>\n\t\t\t\t\t<string>411.IBPluginDependency</string>\n\t\t\t\t\t<string>412.IBPluginDependency</string>\n\t\t\t\t\t<string>413.IBPluginDependency</string>\n\t\t\t\t\t<string>414.IBPluginDependency</string>\n\t\t\t\t\t<string>415.IBPluginDependency</string>\n\t\t\t\t\t<string>416.IBPluginDependency</string>\n\t\t\t\t\t<string>417.IBPluginDependency</string>\n\t\t\t\t\t<string>418.IBPluginDependency</string>\n\t\t\t\t\t<string>419.IBPluginDependency</string>\n\t\t\t\t\t<string>450.IBPluginDependency</string>\n\t\t\t\t\t<string>451.IBEditorWindowLastContentRect</string>\n\t\t\t\t\t<string>451.IBPluginDependency</string>\n\t\t\t\t\t<string>452.IBPluginDependency</string>\n\t\t\t\t\t<string>453.IBPluginDependency</string>\n\t\t\t\t\t<string>454.IBPluginDependency</string>\n\t\t\t\t\t<string>457.IBPluginDependency</string>\n\t\t\t\t\t<string>459.IBPluginDependency</string>\n\t\t\t\t\t<string>460.IBPluginDependency</string>\n\t\t\t\t\t<string>462.IBPluginDependency</string>\n\t\t\t\t\t<string>465.IBPluginDependency</string>\n\t\t\t\t\t<string>466.IBPluginDependency</string>\n\t\t\t\t\t<string>485.IBPluginDependency</string>\n\t\t\t\t\t<string>490.IBPluginDependency</string>\n\t\t\t\t\t<string>491.IBEditorWindowLastContentRect</string>\n\t\t\t\t\t<string>491.IBPluginDependency</string>\n\t\t\t\t\t<string>492.IBPluginDependency</string>\n\t\t\t\t\t<string>496.IBPluginDependency</string>\n\t\t\t\t\t<string>497.IBEditorWindowLastContentRect</string>\n\t\t\t\t\t<string>497.IBPluginDependency</string>\n\t\t\t\t\t<string>498.IBPluginDependency</string>\n\t\t\t\t\t<string>499.IBPluginDependency</string>\n\t\t\t\t\t<string>5.IBPluginDependency</string>\n\t\t\t\t\t<string>5.ImportedFromIB2</string>\n\t\t\t\t\t<string>500.IBPluginDependency</string>\n\t\t\t\t\t<string>501.IBPluginDependency</string>\n\t\t\t\t\t<string>502.IBPluginDependency</string>\n\t\t\t\t\t<string>503.IBPluginDependency</string>\n\t\t\t\t\t<string>504.IBPluginDependency</string>\n\t\t\t\t\t<string>505.IBPluginDependency</string>\n\t\t\t\t\t<string>506.IBPluginDependency</string>\n\t\t\t\t\t<string>507.IBPluginDependency</string>\n\t\t\t\t\t<string>508.IBEditorWindowLastContentRect</string>\n\t\t\t\t\t<string>508.IBPluginDependency</string>\n\t\t\t\t\t<string>509.IBPluginDependency</string>\n\t\t\t\t\t<string>510.IBPluginDependency</string>\n\t\t\t\t\t<string>511.IBPluginDependency</string>\n\t\t\t\t\t<string>512.IBPluginDependency</string>\n\t\t\t\t\t<string>513.IBPluginDependency</string>\n\t\t\t\t\t<string>514.IBPluginDependency</string>\n\t\t\t\t\t<string>515.IBPluginDependency</string>\n\t\t\t\t\t<string>516.IBPluginDependency</string>\n\t\t\t\t\t<string>517.IBPluginDependency</string>\n\t\t\t\t\t<string>533.IBPluginDependency</string>\n\t\t\t\t\t<string>534.IBPluginDependency</string>\n\t\t\t\t\t<string>535.IBPluginDependency</string>\n\t\t\t\t\t<string>536.IBPluginDependency</string>\n\t\t\t\t\t<string>537.IBPluginDependency</string>\n\t\t\t\t\t<string>538.IBPluginDependency</string>\n\t\t\t\t\t<string>542.IBPluginDependency</string>\n\t\t\t\t\t<string>543.IBPluginDependency</string>\n\t\t\t\t\t<string>550.IBPluginDependency</string>\n\t\t\t\t\t<string>551.IBPluginDependency</string>\n\t\t\t\t\t<string>552.IBPluginDependency</string>\n\t\t\t\t\t<string>553.IBPluginDependency</string>\n\t\t\t\t\t<string>557.IBPluginDependency</string>\n\t\t\t\t\t<string>558.IBPluginDependency</string>\n\t\t\t\t\t<string>559.IBPluginDependency</string>\n\t\t\t\t\t<string>56.IBPluginDependency</string>\n\t\t\t\t\t<string>56.ImportedFromIB2</string>\n\t\t\t\t\t<string>560.IBPluginDependency</string>\n\t\t\t\t\t<string>561.IBPluginDependency</string>\n\t\t\t\t\t<string>562.IBPluginDependency</string>\n\t\t\t\t\t<string>57.IBEditorWindowLastContentRect</string>\n\t\t\t\t\t<string>57.IBPluginDependency</string>\n\t\t\t\t\t<string>57.ImportedFromIB2</string>\n\t\t\t\t\t<string>57.editorWindowContentRectSynchronizationRect</string>\n\t\t\t\t\t<string>58.IBPluginDependency</string>\n\t\t\t\t\t<string>58.ImportedFromIB2</string>\n\t\t\t\t\t<string>72.IBPluginDependency</string>\n\t\t\t\t\t<string>72.ImportedFromIB2</string>\n\t\t\t\t\t<string>73.IBPluginDependency</string>\n\t\t\t\t\t<string>73.ImportedFromIB2</string>\n\t\t\t\t\t<string>74.IBPluginDependency</string>\n\t\t\t\t\t<string>74.ImportedFromIB2</string>\n\t\t\t\t\t<string>75.IBPluginDependency</string>\n\t\t\t\t\t<string>75.ImportedFromIB2</string>\n\t\t\t\t\t<string>77.IBPluginDependency</string>\n\t\t\t\t\t<string>77.ImportedFromIB2</string>\n\t\t\t\t\t<string>78.IBPluginDependency</string>\n\t\t\t\t\t<string>78.ImportedFromIB2</string>\n\t\t\t\t\t<string>79.IBPluginDependency</string>\n\t\t\t\t\t<string>79.ImportedFromIB2</string>\n\t\t\t\t\t<string>80.IBPluginDependency</string>\n\t\t\t\t\t<string>80.ImportedFromIB2</string>\n\t\t\t\t\t<string>81.IBEditorWindowLastContentRect</string>\n\t\t\t\t\t<string>81.IBPluginDependency</string>\n\t\t\t\t\t<string>81.ImportedFromIB2</string>\n\t\t\t\t\t<string>81.editorWindowContentRectSynchronizationRect</string>\n\t\t\t\t\t<string>82.IBPluginDependency</string>\n\t\t\t\t\t<string>82.ImportedFromIB2</string>\n\t\t\t\t\t<string>83.IBPluginDependency</string>\n\t\t\t\t\t<string>83.ImportedFromIB2</string>\n\t\t\t\t\t<string>92.IBPluginDependency</string>\n\t\t\t\t\t<string>92.ImportedFromIB2</string>\n\t\t\t\t</object>\n\t\t\t\t<object class=\"NSMutableArray\" key=\"dict.values\">\n\t\t\t\t\t<bool key=\"EncodedWithXMLCoder\">YES</bool>\n\t\t\t\t\t<string>com.apple.InterfaceBuilder.CocoaPlugin</string>\n\t\t\t\t\t<string>com.apple.InterfaceBuilder.CocoaPlugin</string>\n\t\t\t\t\t<integer value=\"1\"/>\n\t\t\t\t\t<string>com.apple.InterfaceBuilder.CocoaPlugin</string>\n\t\t\t\t\t<integer value=\"1\"/>\n\t\t\t\t\t<string>com.apple.InterfaceBuilder.CocoaPlugin</string>\n\t\t\t\t\t<integer value=\"1\"/>\n\t\t\t\t\t<string>{{522, 812}, {146, 23}}</string>\n\t\t\t\t\t<string>com.apple.InterfaceBuilder.CocoaPlugin</string>\n\t\t\t\t\t<integer value=\"1\"/>\n\t\t\t\t\t<string>com.apple.InterfaceBuilder.CocoaPlugin</string>\n\t\t\t\t\t<integer value=\"1\"/>\n\t\t\t\t\t<string>com.apple.InterfaceBuilder.CocoaPlugin</string>\n\t\t\t\t\t<integer value=\"1\"/>\n\t\t\t\t\t<string>{{436, 809}, {64, 6}}</string>\n\t\t\t\t\t<string>com.apple.InterfaceBuilder.CocoaPlugin</string>\n\t\t\t\t\t<integer value=\"1\"/>\n\t\t\t\t\t<string>com.apple.InterfaceBuilder.CocoaPlugin</string>\n\t\t\t\t\t<integer value=\"1\"/>\n\t\t\t\t\t<string>com.apple.InterfaceBuilder.CocoaPlugin</string>\n\t\t\t\t\t<integer value=\"1\"/>\n\t\t\t\t\t<string>com.apple.InterfaceBuilder.CocoaPlugin</string>\n\t\t\t\t\t<integer value=\"1\"/>\n\t\t\t\t\t<string>com.apple.InterfaceBuilder.CocoaPlugin</string>\n\t\t\t\t\t<integer value=\"1\"/>\n\t\t\t\t\t<string>com.apple.InterfaceBuilder.CocoaPlugin</string>\n\t\t\t\t\t<integer value=\"1\"/>\n\t\t\t\t\t<string>com.apple.InterfaceBuilder.CocoaPlugin</string>\n\t\t\t\t\t<integer value=\"1\"/>\n\t\t\t\t\t<string>com.apple.InterfaceBuilder.CocoaPlugin</string>\n\t\t\t\t\t<integer value=\"1\"/>\n\t\t\t\t\t<string>com.apple.InterfaceBuilder.CocoaPlugin</string>\n\t\t\t\t\t<integer value=\"1\"/>\n\t\t\t\t\t<string>com.apple.InterfaceBuilder.CocoaPlugin</string>\n\t\t\t\t\t<integer value=\"1\"/>\n\t\t\t\t\t<string>com.apple.InterfaceBuilder.CocoaPlugin</string>\n\t\t\t\t\t<integer value=\"1\"/>\n\t\t\t\t\t<string>com.apple.InterfaceBuilder.CocoaPlugin</string>\n\t\t\t\t\t<integer value=\"1\"/>\n\t\t\t\t\t<string>com.apple.InterfaceBuilder.CocoaPlugin</string>\n\t\t\t\t\t<integer value=\"1\"/>\n\t\t\t\t\t<string>com.apple.InterfaceBuilder.CocoaPlugin</string>\n\t\t\t\t\t<integer value=\"1\"/>\n\t\t\t\t\t<string>{{753, 187}, {275, 113}}</string>\n\t\t\t\t\t<string>com.apple.InterfaceBuilder.CocoaPlugin</string>\n\t\t\t\t\t<integer value=\"1\"/>\n\t\t\t\t\t<string>{{608, 612}, {275, 83}}</string>\n\t\t\t\t\t<string>com.apple.InterfaceBuilder.CocoaPlugin</string>\n\t\t\t\t\t<integer value=\"1\"/>\n\t\t\t\t\t<string>com.apple.InterfaceBuilder.CocoaPlugin</string>\n\t\t\t\t\t<integer value=\"1\"/>\n\t\t\t\t\t<string>com.apple.InterfaceBuilder.CocoaPlugin</string>\n\t\t\t\t\t<integer value=\"1\"/>\n\t\t\t\t\t<string>com.apple.InterfaceBuilder.CocoaPlugin</string>\n\t\t\t\t\t<integer value=\"1\"/>\n\t\t\t\t\t<string>{{547, 180}, {254, 283}}</string>\n\t\t\t\t\t<string>com.apple.InterfaceBuilder.CocoaPlugin</string>\n\t\t\t\t\t<integer value=\"1\"/>\n\t\t\t\t\t<string>{{187, 434}, {243, 243}}</string>\n\t\t\t\t\t<string>com.apple.InterfaceBuilder.CocoaPlugin</string>\n\t\t\t\t\t<integer value=\"1\"/>\n\t\t\t\t\t<string>com.apple.InterfaceBuilder.CocoaPlugin</string>\n\t\t\t\t\t<integer value=\"1\"/>\n\t\t\t\t\t<string>com.apple.InterfaceBuilder.CocoaPlugin</string>\n\t\t\t\t\t<integer value=\"1\"/>\n\t\t\t\t\t<string>com.apple.InterfaceBuilder.CocoaPlugin</string>\n\t\t\t\t\t<integer value=\"1\"/>\n\t\t\t\t\t<string>com.apple.InterfaceBuilder.CocoaPlugin</string>\n\t\t\t\t\t<integer value=\"1\"/>\n\t\t\t\t\t<string>com.apple.InterfaceBuilder.CocoaPlugin</string>\n\t\t\t\t\t<integer value=\"1\"/>\n\t\t\t\t\t<string>com.apple.InterfaceBuilder.CocoaPlugin</string>\n\t\t\t\t\t<integer value=\"1\"/>\n\t\t\t\t\t<string>{{608, 612}, {167, 43}}</string>\n\t\t\t\t\t<string>com.apple.InterfaceBuilder.CocoaPlugin</string>\n\t\t\t\t\t<integer value=\"1\"/>\n\t\t\t\t\t<string>com.apple.InterfaceBuilder.CocoaPlugin</string>\n\t\t\t\t\t<integer value=\"1\"/>\n\t\t\t\t\t<string>com.apple.InterfaceBuilder.CocoaPlugin</string>\n\t\t\t\t\t<integer value=\"1\"/>\n\t\t\t\t\t<string>com.apple.InterfaceBuilder.CocoaPlugin</string>\n\t\t\t\t\t<integer value=\"1\"/>\n\t\t\t\t\t<string>com.apple.InterfaceBuilder.CocoaPlugin</string>\n\t\t\t\t\t<integer value=\"1\"/>\n\t\t\t\t\t<string>com.apple.InterfaceBuilder.CocoaPlugin</string>\n\t\t\t\t\t<integer value=\"1\"/>\n\t\t\t\t\t<string>com.apple.InterfaceBuilder.CocoaPlugin</string>\n\t\t\t\t\t<integer value=\"1\"/>\n\t\t\t\t\t<string>{{753, 217}, {238, 103}}</string>\n\t\t\t\t\t<string>com.apple.InterfaceBuilder.CocoaPlugin</string>\n\t\t\t\t\t<integer value=\"1\"/>\n\t\t\t\t\t<string>{{608, 612}, {241, 103}}</string>\n\t\t\t\t\t<string>com.apple.InterfaceBuilder.CocoaPlugin</string>\n\t\t\t\t\t<integer value=\"1\"/>\n\t\t\t\t\t<string>com.apple.InterfaceBuilder.CocoaPlugin</string>\n\t\t\t\t\t<integer value=\"1\"/>\n\t\t\t\t\t<string>com.apple.InterfaceBuilder.CocoaPlugin</string>\n\t\t\t\t\t<integer value=\"1\"/>\n\t\t\t\t\t<string>com.apple.InterfaceBuilder.CocoaPlugin</string>\n\t\t\t\t\t<integer value=\"1\"/>\n\t\t\t\t\t<string>{{654, 239}, {194, 73}}</string>\n\t\t\t\t\t<string>com.apple.InterfaceBuilder.CocoaPlugin</string>\n\t\t\t\t\t<integer value=\"1\"/>\n\t\t\t\t\t<string>{{525, 802}, {197, 73}}</string>\n\t\t\t\t\t<string>{{380, 836}, {442, 20}}</string>\n\t\t\t\t\t<string>com.apple.InterfaceBuilder.CocoaPlugin</string>\n\t\t\t\t\t<integer value=\"1\"/>\n\t\t\t\t\t<string>{74, 862}</string>\n\t\t\t\t\t<string>{{6, 978}, {478, 20}}</string>\n\t\t\t\t\t<string>com.apple.InterfaceBuilder.CocoaPlugin</string>\n\t\t\t\t\t<string>{{604, 269}, {231, 43}}</string>\n\t\t\t\t\t<string>com.apple.InterfaceBuilder.CocoaPlugin</string>\n\t\t\t\t\t<string>{{475, 832}, {234, 43}}</string>\n\t\t\t\t\t<string>com.apple.InterfaceBuilder.CocoaPlugin</string>\n\t\t\t\t\t<string>com.apple.InterfaceBuilder.CocoaPlugin</string>\n\t\t\t\t\t<string>com.apple.InterfaceBuilder.CocoaPlugin</string>\n\t\t\t\t\t<integer value=\"1\"/>\n\t\t\t\t\t<string>com.apple.InterfaceBuilder.CocoaPlugin</string>\n\t\t\t\t\t<integer value=\"1\"/>\n\t\t\t\t\t<string>{{746, 287}, {220, 133}}</string>\n\t\t\t\t\t<string>com.apple.InterfaceBuilder.CocoaPlugin</string>\n\t\t\t\t\t<integer value=\"1\"/>\n\t\t\t\t\t<string>{{608, 612}, {215, 63}}</string>\n\t\t\t\t\t<string>com.apple.InterfaceBuilder.CocoaPlugin</string>\n\t\t\t\t\t<integer value=\"1\"/>\n\t\t\t\t\t<string>com.apple.InterfaceBuilder.CocoaPlugin</string>\n\t\t\t\t\t<integer value=\"1\"/>\n\t\t\t\t\t<string>com.apple.InterfaceBuilder.CocoaPlugin</string>\n\t\t\t\t\t<integer value=\"1\"/>\n\t\t\t\t\t<string>{{183, 462}, {497, 322}}</string>\n\t\t\t\t\t<string>com.apple.InterfaceBuilder.CocoaPlugin</string>\n\t\t\t\t\t<string>{{183, 462}, {497, 322}}</string>\n\t\t\t\t\t<integer value=\"1\"/>\n\t\t\t\t\t<string>{{33, 99}, {480, 360}}</string>\n\t\t\t\t\t<boolean value=\"NO\"/>\n\t\t\t\t\t<string>{9999, 122}</string>\n\t\t\t\t\t<string>com.apple.InterfaceBuilder.CocoaPlugin</string>\n\t\t\t\t\t<string>com.apple.InterfaceBuilder.CocoaPlugin</string>\n\t\t\t\t\t<string>{{591, 420}, {83, 43}}</string>\n\t\t\t\t\t<string>com.apple.InterfaceBuilder.CocoaPlugin</string>\n\t\t\t\t\t<string>com.apple.InterfaceBuilder.CocoaPlugin</string>\n\t\t\t\t\t<string>{{523, 2}, {178, 283}}</string>\n\t\t\t\t\t<string>com.apple.InterfaceBuilder.CocoaPlugin</string>\n\t\t\t\t\t<string>com.apple.InterfaceBuilder.CocoaPlugin</string>\n\t\t\t\t\t<string>com.apple.InterfaceBuilder.CocoaPlugin</string>\n\t\t\t\t\t<string>com.apple.InterfaceBuilder.CocoaPlugin</string>\n\t\t\t\t\t<string>com.apple.InterfaceBuilder.CocoaPlugin</string>\n\t\t\t\t\t<string>com.apple.InterfaceBuilder.CocoaPlugin</string>\n\t\t\t\t\t<string>com.apple.InterfaceBuilder.CocoaPlugin</string>\n\t\t\t\t\t<string>com.apple.InterfaceBuilder.CocoaPlugin</string>\n\t\t\t\t\t<string>com.apple.InterfaceBuilder.CocoaPlugin</string>\n\t\t\t\t\t<string>com.apple.InterfaceBuilder.CocoaPlugin</string>\n\t\t\t\t\t<string>com.apple.InterfaceBuilder.CocoaPlugin</string>\n\t\t\t\t\t<string>com.apple.InterfaceBuilder.CocoaPlugin</string>\n\t\t\t\t\t<string>com.apple.InterfaceBuilder.CocoaPlugin</string>\n\t\t\t\t\t<string>com.apple.InterfaceBuilder.CocoaPlugin</string>\n\t\t\t\t\t<string>com.apple.InterfaceBuilder.CocoaPlugin</string>\n\t\t\t\t\t<string>com.apple.InterfaceBuilder.CocoaPlugin</string>\n\t\t\t\t\t<string>com.apple.InterfaceBuilder.CocoaPlugin</string>\n\t\t\t\t\t<string>com.apple.InterfaceBuilder.CocoaPlugin</string>\n\t\t\t\t\t<string>com.apple.InterfaceBuilder.CocoaPlugin</string>\n\t\t\t\t\t<string>com.apple.InterfaceBuilder.CocoaPlugin</string>\n\t\t\t\t\t<string>com.apple.InterfaceBuilder.CocoaPlugin</string>\n\t\t\t\t\t<string>com.apple.InterfaceBuilder.CocoaPlugin</string>\n\t\t\t\t\t<string>com.apple.InterfaceBuilder.CocoaPlugin</string>\n\t\t\t\t\t<string>com.apple.InterfaceBuilder.CocoaPlugin</string>\n\t\t\t\t\t<string>com.apple.InterfaceBuilder.CocoaPlugin</string>\n\t\t\t\t\t<string>com.apple.InterfaceBuilder.CocoaPlugin</string>\n\t\t\t\t\t<string>com.apple.InterfaceBuilder.CocoaPlugin</string>\n\t\t\t\t\t<string>com.apple.InterfaceBuilder.CocoaPlugin</string>\n\t\t\t\t\t<string>com.apple.InterfaceBuilder.CocoaPlugin</string>\n\t\t\t\t\t<string>com.apple.InterfaceBuilder.CocoaPlugin</string>\n\t\t\t\t\t<string>com.apple.InterfaceBuilder.CocoaPlugin</string>\n\t\t\t\t\t<string>com.apple.InterfaceBuilder.CocoaPlugin</string>\n\t\t\t\t\t<string>com.apple.InterfaceBuilder.CocoaPlugin</string>\n\t\t\t\t\t<string>{{753, 197}, {170, 63}}</string>\n\t\t\t\t\t<string>com.apple.InterfaceBuilder.CocoaPlugin</string>\n\t\t\t\t\t<string>com.apple.InterfaceBuilder.CocoaPlugin</string>\n\t\t\t\t\t<string>com.apple.InterfaceBuilder.CocoaPlugin</string>\n\t\t\t\t\t<string>com.apple.InterfaceBuilder.CocoaPlugin</string>\n\t\t\t\t\t<string>com.apple.InterfaceBuilder.CocoaPlugin</string>\n\t\t\t\t\t<string>com.apple.InterfaceBuilder.CocoaPlugin</string>\n\t\t\t\t\t<string>com.apple.InterfaceBuilder.CocoaPlugin</string>\n\t\t\t\t\t<string>com.apple.InterfaceBuilder.CocoaPlugin</string>\n\t\t\t\t\t<string>com.apple.InterfaceBuilder.CocoaPlugin</string>\n\t\t\t\t\t<string>com.apple.InterfaceBuilder.CocoaPlugin</string>\n\t\t\t\t\t<string>com.apple.InterfaceBuilder.CocoaPlugin</string>\n\t\t\t\t\t<string>com.apple.InterfaceBuilder.CocoaPlugin</string>\n\t\t\t\t\t<string>{{725, 289}, {246, 23}}</string>\n\t\t\t\t\t<string>com.apple.InterfaceBuilder.CocoaPlugin</string>\n\t\t\t\t\t<string>com.apple.InterfaceBuilder.CocoaPlugin</string>\n\t\t\t\t\t<string>com.apple.InterfaceBuilder.CocoaPlugin</string>\n\t\t\t\t\t<string>{{674, 260}, {204, 183}}</string>\n\t\t\t\t\t<string>com.apple.InterfaceBuilder.CocoaPlugin</string>\n\t\t\t\t\t<string>com.apple.InterfaceBuilder.CocoaPlugin</string>\n\t\t\t\t\t<string>com.apple.InterfaceBuilder.CocoaPlugin</string>\n\t\t\t\t\t<string>com.apple.InterfaceBuilder.CocoaPlugin</string>\n\t\t\t\t\t<integer value=\"1\"/>\n\t\t\t\t\t<string>com.apple.InterfaceBuilder.CocoaPlugin</string>\n\t\t\t\t\t<string>com.apple.InterfaceBuilder.CocoaPlugin</string>\n\t\t\t\t\t<string>com.apple.InterfaceBuilder.CocoaPlugin</string>\n\t\t\t\t\t<string>com.apple.InterfaceBuilder.CocoaPlugin</string>\n\t\t\t\t\t<string>com.apple.InterfaceBuilder.CocoaPlugin</string>\n\t\t\t\t\t<string>com.apple.InterfaceBuilder.CocoaPlugin</string>\n\t\t\t\t\t<string>com.apple.InterfaceBuilder.CocoaPlugin</string>\n\t\t\t\t\t<string>com.apple.InterfaceBuilder.CocoaPlugin</string>\n\t\t\t\t\t<string>{{878, 180}, {164, 173}}</string>\n\t\t\t\t\t<string>com.apple.InterfaceBuilder.CocoaPlugin</string>\n\t\t\t\t\t<string>com.apple.InterfaceBuilder.CocoaPlugin</string>\n\t\t\t\t\t<string>com.apple.InterfaceBuilder.CocoaPlugin</string>\n\t\t\t\t\t<string>com.apple.InterfaceBuilder.CocoaPlugin</string>\n\t\t\t\t\t<string>com.apple.InterfaceBuilder.CocoaPlugin</string>\n\t\t\t\t\t<string>com.apple.InterfaceBuilder.CocoaPlugin</string>\n\t\t\t\t\t<string>com.apple.InterfaceBuilder.CocoaPlugin</string>\n\t\t\t\t\t<string>com.apple.InterfaceBuilder.CocoaPlugin</string>\n\t\t\t\t\t<string>com.apple.InterfaceBuilder.CocoaPlugin</string>\n\t\t\t\t\t<string>com.apple.InterfaceBuilder.CocoaPlugin</string>\n\t\t\t\t\t<string>com.apple.InterfaceBuilder.CocoaPlugin</string>\n\t\t\t\t\t<string>com.apple.InterfaceBuilder.CocoaPlugin</string>\n\t\t\t\t\t<string>com.apple.InterfaceBuilder.CocoaPlugin</string>\n\t\t\t\t\t<string>com.apple.InterfaceBuilder.CocoaPlugin</string>\n\t\t\t\t\t<string>com.apple.InterfaceBuilder.CocoaPlugin</string>\n\t\t\t\t\t<string>com.apple.InterfaceBuilder.CocoaPlugin</string>\n\t\t\t\t\t<string>com.apple.InterfaceBuilder.CocoaPlugin</string>\n\t\t\t\t\t<string>com.apple.InterfaceBuilder.CocoaPlugin</string>\n\t\t\t\t\t<string>com.apple.InterfaceBuilder.CocoaPlugin</string>\n\t\t\t\t\t<string>com.apple.InterfaceBuilder.CocoaPlugin</string>\n\t\t\t\t\t<string>com.apple.InterfaceBuilder.CocoaPlugin</string>\n\t\t\t\t\t<string>com.apple.InterfaceBuilder.CocoaPlugin</string>\n\t\t\t\t\t<string>com.apple.InterfaceBuilder.CocoaPlugin</string>\n\t\t\t\t\t<string>com.apple.InterfaceBuilder.CocoaPlugin</string>\n\t\t\t\t\t<string>com.apple.InterfaceBuilder.CocoaPlugin</string>\n\t\t\t\t\t<string>com.apple.InterfaceBuilder.CocoaPlugin</string>\n\t\t\t\t\t<integer value=\"1\"/>\n\t\t\t\t\t<string>com.apple.InterfaceBuilder.CocoaPlugin</string>\n\t\t\t\t\t<string>com.apple.InterfaceBuilder.CocoaPlugin</string>\n\t\t\t\t\t<string>com.apple.InterfaceBuilder.CocoaPlugin</string>\n\t\t\t\t\t<string>{{286, 129}, {275, 183}}</string>\n\t\t\t\t\t<string>com.apple.InterfaceBuilder.CocoaPlugin</string>\n\t\t\t\t\t<integer value=\"1\"/>\n\t\t\t\t\t<string>{{23, 794}, {245, 183}}</string>\n\t\t\t\t\t<string>com.apple.InterfaceBuilder.CocoaPlugin</string>\n\t\t\t\t\t<integer value=\"1\"/>\n\t\t\t\t\t<string>com.apple.InterfaceBuilder.CocoaPlugin</string>\n\t\t\t\t\t<integer value=\"1\"/>\n\t\t\t\t\t<string>com.apple.InterfaceBuilder.CocoaPlugin</string>\n\t\t\t\t\t<integer value=\"1\"/>\n\t\t\t\t\t<string>com.apple.InterfaceBuilder.CocoaPlugin</string>\n\t\t\t\t\t<integer value=\"1\"/>\n\t\t\t\t\t<string>com.apple.InterfaceBuilder.CocoaPlugin</string>\n\t\t\t\t\t<integer value=\"1\"/>\n\t\t\t\t\t<string>com.apple.InterfaceBuilder.CocoaPlugin</string>\n\t\t\t\t\t<integer value=\"1\"/>\n\t\t\t\t\t<string>com.apple.InterfaceBuilder.CocoaPlugin</string>\n\t\t\t\t\t<integer value=\"1\"/>\n\t\t\t\t\t<string>com.apple.InterfaceBuilder.CocoaPlugin</string>\n\t\t\t\t\t<integer value=\"1\"/>\n\t\t\t\t\t<string>com.apple.InterfaceBuilder.CocoaPlugin</string>\n\t\t\t\t\t<integer value=\"1\"/>\n\t\t\t\t\t<string>{{452, 109}, {196, 203}}</string>\n\t\t\t\t\t<string>com.apple.InterfaceBuilder.CocoaPlugin</string>\n\t\t\t\t\t<integer value=\"1\"/>\n\t\t\t\t\t<string>{{145, 474}, {199, 203}}</string>\n\t\t\t\t\t<string>com.apple.InterfaceBuilder.CocoaPlugin</string>\n\t\t\t\t\t<integer value=\"1\"/>\n\t\t\t\t\t<string>com.apple.InterfaceBuilder.CocoaPlugin</string>\n\t\t\t\t\t<integer value=\"1\"/>\n\t\t\t\t\t<string>com.apple.InterfaceBuilder.CocoaPlugin</string>\n\t\t\t\t\t<integer value=\"1\"/>\n\t\t\t\t</object>\n\t\t\t</object>\n\t\t\t<object class=\"NSMutableDictionary\" key=\"unlocalizedProperties\">\n\t\t\t\t<bool key=\"EncodedWithXMLCoder\">YES</bool>\n\t\t\t\t<reference key=\"dict.sortedKeys\" ref=\"0\"/>\n\t\t\t\t<object class=\"NSMutableArray\" key=\"dict.values\">\n\t\t\t\t\t<bool key=\"EncodedWithXMLCoder\">YES</bool>\n\t\t\t\t</object>\n\t\t\t</object>\n\t\t\t<nil key=\"activeLocalization\"/>\n\t\t\t<object class=\"NSMutableDictionary\" key=\"localizations\">\n\t\t\t\t<bool key=\"EncodedWithXMLCoder\">YES</bool>\n\t\t\t\t<reference key=\"dict.sortedKeys\" ref=\"0\"/>\n\t\t\t\t<object class=\"NSMutableArray\" key=\"dict.values\">\n\t\t\t\t\t<bool key=\"EncodedWithXMLCoder\">YES</bool>\n\t\t\t\t</object>\n\t\t\t</object>\n\t\t\t<nil key=\"sourceID\"/>\n\t\t\t<int key=\"maxID\">563</int>\n\t\t</object>\n\t\t<object class=\"IBClassDescriber\" key=\"IBDocument.Classes\">\n\t\t\t<object class=\"NSMutableArray\" key=\"referencedPartialClassDescriptions\">\n\t\t\t\t<bool key=\"EncodedWithXMLCoder\">YES</bool>\n\t\t\t\t<object class=\"IBPartialClassDescription\">\n\t\t\t\t\t<string key=\"className\">RandomifyAppDelegate</string>\n\t\t\t\t\t<string key=\"superclassName\">NSObject</string>\n\t\t\t\t\t<object class=\"NSMutableDictionary\" key=\"actions\">\n\t\t\t\t\t\t<bool key=\"EncodedWithXMLCoder\">YES</bool>\n\t\t\t\t\t\t<object class=\"NSArray\" key=\"dict.sortedKeys\">\n\t\t\t\t\t\t\t<bool key=\"EncodedWithXMLCoder\">YES</bool>\n\t\t\t\t\t\t\t<string>loginAndPlay:</string>\n\t\t\t\t\t\t\t<string>playARandomSong:</string>\n\t\t\t\t\t\t\t<string>togglePlay:</string>\n\t\t\t\t\t\t</object>\n\t\t\t\t\t\t<object class=\"NSMutableArray\" key=\"dict.values\">\n\t\t\t\t\t\t\t<bool key=\"EncodedWithXMLCoder\">YES</bool>\n\t\t\t\t\t\t\t<string>id</string>\n\t\t\t\t\t\t\t<string>id</string>\n\t\t\t\t\t\t\t<string>id</string>\n\t\t\t\t\t\t</object>\n\t\t\t\t\t</object>\n\t\t\t\t\t<object class=\"NSMutableDictionary\" key=\"outlets\">\n\t\t\t\t\t\t<bool key=\"EncodedWithXMLCoder\">YES</bool>\n\t\t\t\t\t\t<object class=\"NSArray\" key=\"dict.sortedKeys\">\n\t\t\t\t\t\t\t<bool key=\"EncodedWithXMLCoder\">YES</bool>\n\t\t\t\t\t\t\t<string>log</string>\n\t\t\t\t\t\t\t<string>password</string>\n\t\t\t\t\t\t\t<string>playButton</string>\n\t\t\t\t\t\t\t<string>status</string>\n\t\t\t\t\t\t\t<string>username</string>\n\t\t\t\t\t\t\t<string>window</string>\n\t\t\t\t\t\t</object>\n\t\t\t\t\t\t<object class=\"NSMutableArray\" key=\"dict.values\">\n\t\t\t\t\t\t\t<bool key=\"EncodedWithXMLCoder\">YES</bool>\n\t\t\t\t\t\t\t<string>NSTextField</string>\n\t\t\t\t\t\t\t<string>NSTextField</string>\n\t\t\t\t\t\t\t<string>NSButton</string>\n\t\t\t\t\t\t\t<string>NSTextField</string>\n\t\t\t\t\t\t\t<string>NSTextField</string>\n\t\t\t\t\t\t\t<string>NSWindow</string>\n\t\t\t\t\t\t</object>\n\t\t\t\t\t</object>\n\t\t\t\t\t<object class=\"IBClassDescriptionSource\" key=\"sourceIdentifier\">\n\t\t\t\t\t\t<string key=\"majorKey\">IBProjectSource</string>\n\t\t\t\t\t\t<string key=\"minorKey\">RandomifyAppDelegate.h</string>\n\t\t\t\t\t</object>\n\t\t\t\t</object>\n\t\t\t</object>\n\t\t</object>\n\t\t<int key=\"IBDocument.localizationMode\">0</int>\n\t\t<object class=\"NSMutableDictionary\" key=\"IBDocument.PluginDeclaredDependencies\">\n\t\t\t<string key=\"NS.key.0\">com.apple.InterfaceBuilder.CocoaPlugin.macosx</string>\n\t\t\t<integer value=\"1050\" key=\"NS.object.0\"/>\n\t\t</object>\n\t\t<object class=\"NSMutableDictionary\" key=\"IBDocument.PluginDeclaredDependencyDefaults\">\n\t\t\t<string key=\"NS.key.0\">com.apple.InterfaceBuilder.CocoaPlugin.macosx</string>\n\t\t\t<integer value=\"1060\" key=\"NS.object.0\"/>\n\t\t</object>\n\t\t<object class=\"NSMutableDictionary\" key=\"IBDocument.PluginDeclaredDevelopmentDependencies\">\n\t\t\t<string key=\"NS.key.0\">com.apple.InterfaceBuilder.CocoaPlugin.InterfaceBuilder3</string>\n\t\t\t<integer value=\"3000\" key=\"NS.object.0\"/>\n\t\t</object>\n\t\t<bool key=\"IBDocument.PluginDeclaredDependenciesTrackSystemTargetVersion\">YES</bool>\n\t\t<string key=\"IBDocument.LastKnownRelativeProjectPath\">../Randomify.xcodeproj</string>\n\t\t<int key=\"IBDocument.defaultPropertyAccessControl\">3</int>\n\t</data>\n</archive>\n"
  },
  {
    "path": "libspotify/examples/Randomify/Randomify-Info.plist",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n<dict>\n\t<key>CFBundleDevelopmentRegion</key>\n\t<string>English</string>\n\t<key>CFBundleExecutable</key>\n\t<string>${EXECUTABLE_NAME}</string>\n\t<key>CFBundleIconFile</key>\n\t<string></string>\n\t<key>CFBundleIdentifier</key>\n\t<string>com.spotify.randomify</string>\n\t<key>CFBundleInfoDictionaryVersion</key>\n\t<string>6.0</string>\n\t<key>CFBundleName</key>\n\t<string>${PRODUCT_NAME}</string>\n\t<key>CFBundlePackageType</key>\n\t<string>APPL</string>\n\t<key>CFBundleShortVersionString</key>\n\t<string>1.0</string>\n\t<key>CFBundleSignature</key>\n\t<string>????</string>\n\t<key>CFBundleVersion</key>\n\t<string>1</string>\n\t<key>LSMinimumSystemVersion</key>\n\t<string>${MACOSX_DEPLOYMENT_TARGET}</string>\n\t<key>NSMainNibFile</key>\n\t<string>MainMenu</string>\n\t<key>NSPrincipalClass</key>\n\t<string>NSApplication</string>\n</dict>\n</plist>\n"
  },
  {
    "path": "libspotify/examples/Randomify/Randomify.xcodeproj/project.pbxproj",
    "content": "// !$*UTF8*$!\n{\n\tarchiveVersion = 1;\n\tclasses = {\n\t};\n\tobjectVersion = 45;\n\tobjects = {\n\n/* Begin PBXBuildFile section */\n\t\t0575227B1161F3A5003FFC9D /* libspotify.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0575227A1161F3A5003FFC9D /* libspotify.framework */; };\n\t\t057522801161F3C9003FFC9D /* libspotify.framework in Copy Frameworks */ = {isa = PBXBuildFile; fileRef = 0575227A1161F3A5003FFC9D /* libspotify.framework */; };\n\t\t057522901161F4AE003FFC9D /* appkey.c in Sources */ = {isa = PBXBuildFile; fileRef = 0575228F1161F4AE003FFC9D /* appkey.c */; };\n\t\t057522BB1161F629003FFC9D /* audio.c in Sources */ = {isa = PBXBuildFile; fileRef = 057522BA1161F629003FFC9D /* audio.c */; };\n\t\t057522C01161F6F7003FFC9D /* SpotifySession.m in Sources */ = {isa = PBXBuildFile; fileRef = 057522BF1161F6F7003FFC9D /* SpotifySession.m */; };\n\t\t05752469116225C4003FFC9D /* SpotifyPlaylist.m in Sources */ = {isa = PBXBuildFile; fileRef = 05752468116225C4003FFC9D /* SpotifyPlaylist.m */; };\n\t\t057524E11162303B003FFC9D /* SpotifyTrack.m in Sources */ = {isa = PBXBuildFile; fileRef = 057524E01162303B003FFC9D /* SpotifyTrack.m */; };\n\t\t057526DD116248B1003FFC9D /* osx-audio.c in Sources */ = {isa = PBXBuildFile; fileRef = 057526DC116248B1003FFC9D /* osx-audio.c */; };\n\t\t057526E1116248D4003FFC9D /* AudioToolbox.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 057526E0116248D4003FFC9D /* AudioToolbox.framework */; };\n\t\t1DDD58160DA1D0A300B32029 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 1DDD58140DA1D0A300B32029 /* MainMenu.xib */; };\n\t\t256AC3DA0F4B6AC300CF3369 /* RandomifyAppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 256AC3D90F4B6AC300CF3369 /* RandomifyAppDelegate.m */; };\n\t\t8D11072B0486CEB800E47090 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 089C165CFE840E0CC02AAC07 /* InfoPlist.strings */; };\n\t\t8D11072D0486CEB800E47090 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 29B97316FDCFA39411CA2CEA /* main.m */; settings = {ATTRIBUTES = (); }; };\n\t\t8D11072F0486CEB800E47090 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1058C7A1FEA54F0111CA2CBB /* Cocoa.framework */; };\n/* End PBXBuildFile section */\n\n/* Begin PBXCopyFilesBuildPhase section */\n\t\t0575226B1161F20D003FFC9D /* Copy Frameworks */ = {\n\t\t\tisa = PBXCopyFilesBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tdstPath = \"\";\n\t\t\tdstSubfolderSpec = 10;\n\t\t\tfiles = (\n\t\t\t\t057522801161F3C9003FFC9D /* libspotify.framework in Copy Frameworks */,\n\t\t\t);\n\t\t\tname = \"Copy Frameworks\";\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n/* End PBXCopyFilesBuildPhase section */\n\n/* Begin PBXFileReference section */\n\t\t0575227A1161F3A5003FFC9D /* libspotify.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = libspotify.framework; path = ../../libspotify.framework; sourceTree = SOURCE_ROOT; };\n\t\t0575228F1161F4AE003FFC9D /* appkey.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = appkey.c; path = ../appkey.c; sourceTree = SOURCE_ROOT; };\n\t\t057522B01161F609003FFC9D /* audio.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = audio.h; path = ../jukebox/audio.h; sourceTree = SOURCE_ROOT; };\n\t\t057522B21161F609003FFC9D /* queue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = queue.h; path = ../jukebox/queue.h; sourceTree = SOURCE_ROOT; };\n\t\t057522BA1161F629003FFC9D /* audio.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = audio.c; path = ../jukebox/audio.c; sourceTree = SOURCE_ROOT; };\n\t\t057522BE1161F6F7003FFC9D /* SpotifySession.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SpotifySession.h; sourceTree = \"<group>\"; };\n\t\t057522BF1161F6F7003FFC9D /* SpotifySession.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SpotifySession.m; sourceTree = \"<group>\"; };\n\t\t05752467116225C4003FFC9D /* SpotifyPlaylist.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SpotifyPlaylist.h; sourceTree = \"<group>\"; };\n\t\t05752468116225C4003FFC9D /* SpotifyPlaylist.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SpotifyPlaylist.m; sourceTree = \"<group>\"; };\n\t\t057524DF1162303B003FFC9D /* SpotifyTrack.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SpotifyTrack.h; sourceTree = \"<group>\"; };\n\t\t057524E01162303B003FFC9D /* SpotifyTrack.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SpotifyTrack.m; sourceTree = \"<group>\"; };\n\t\t057526DC116248B1003FFC9D /* osx-audio.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = \"osx-audio.c\"; path = \"../jukebox/osx-audio.c\"; sourceTree = SOURCE_ROOT; };\n\t\t057526E0116248D4003FFC9D /* AudioToolbox.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AudioToolbox.framework; path = System/Library/Frameworks/AudioToolbox.framework; sourceTree = SDKROOT; };\n\t\t089C165DFE840E0CC02AAC07 /* English */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.strings; name = English; path = English.lproj/InfoPlist.strings; sourceTree = \"<group>\"; };\n\t\t1058C7A1FEA54F0111CA2CBB /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = /System/Library/Frameworks/Cocoa.framework; sourceTree = \"<absolute>\"; };\n\t\t1DDD58150DA1D0A300B32029 /* English */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = English; path = English.lproj/MainMenu.xib; sourceTree = \"<group>\"; };\n\t\t256AC3D80F4B6AC300CF3369 /* RandomifyAppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RandomifyAppDelegate.h; sourceTree = \"<group>\"; };\n\t\t256AC3D90F4B6AC300CF3369 /* RandomifyAppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RandomifyAppDelegate.m; sourceTree = \"<group>\"; };\n\t\t256AC3F00F4B6AF500CF3369 /* Randomify_Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Randomify_Prefix.pch; sourceTree = \"<group>\"; };\n\t\t29B97316FDCFA39411CA2CEA /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = \"<group>\"; };\n\t\t8D1107310486CEB800E47090 /* Randomify-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = \"Randomify-Info.plist\"; sourceTree = \"<group>\"; };\n\t\t8D1107320486CEB800E47090 /* Randomify.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Randomify.app; sourceTree = BUILT_PRODUCTS_DIR; };\n/* End PBXFileReference section */\n\n/* Begin PBXFrameworksBuildPhase section */\n\t\t8D11072E0486CEB800E47090 /* Frameworks */ = {\n\t\t\tisa = PBXFrameworksBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\t8D11072F0486CEB800E47090 /* Cocoa.framework in Frameworks */,\n\t\t\t\t0575227B1161F3A5003FFC9D /* libspotify.framework in Frameworks */,\n\t\t\t\t057526E1116248D4003FFC9D /* AudioToolbox.framework in Frameworks */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n/* End PBXFrameworksBuildPhase section */\n\n/* Begin PBXGroup section */\n\t\t080E96DDFE201D6D7F000001 /* Classes */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t256AC3D80F4B6AC300CF3369 /* RandomifyAppDelegate.h */,\n\t\t\t\t256AC3D90F4B6AC300CF3369 /* RandomifyAppDelegate.m */,\n\t\t\t\t057522BE1161F6F7003FFC9D /* SpotifySession.h */,\n\t\t\t\t057522BF1161F6F7003FFC9D /* SpotifySession.m */,\n\t\t\t\t05752467116225C4003FFC9D /* SpotifyPlaylist.h */,\n\t\t\t\t05752468116225C4003FFC9D /* SpotifyPlaylist.m */,\n\t\t\t\t057524DF1162303B003FFC9D /* SpotifyTrack.h */,\n\t\t\t\t057524E01162303B003FFC9D /* SpotifyTrack.m */,\n\t\t\t);\n\t\t\tname = Classes;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t19C28FACFE9D520D11CA2CBB /* Products */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t8D1107320486CEB800E47090 /* Randomify.app */,\n\t\t\t);\n\t\t\tname = Products;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t29B97314FDCFA39411CA2CEA /* Randomify */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t080E96DDFE201D6D7F000001 /* Classes */,\n\t\t\t\t29B97315FDCFA39411CA2CEA /* Other Sources */,\n\t\t\t\t29B97317FDCFA39411CA2CEA /* Resources */,\n\t\t\t\t29B97323FDCFA39411CA2CEA /* Frameworks */,\n\t\t\t\t19C28FACFE9D520D11CA2CBB /* Products */,\n\t\t\t);\n\t\t\tname = Randomify;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t29B97315FDCFA39411CA2CEA /* Other Sources */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t057522B01161F609003FFC9D /* audio.h */,\n\t\t\t\t057522B21161F609003FFC9D /* queue.h */,\n\t\t\t\t057526DC116248B1003FFC9D /* osx-audio.c */,\n\t\t\t\t0575228F1161F4AE003FFC9D /* appkey.c */,\n\t\t\t\t057522BA1161F629003FFC9D /* audio.c */,\n\t\t\t\t256AC3F00F4B6AF500CF3369 /* Randomify_Prefix.pch */,\n\t\t\t\t29B97316FDCFA39411CA2CEA /* main.m */,\n\t\t\t);\n\t\t\tname = \"Other Sources\";\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t29B97317FDCFA39411CA2CEA /* Resources */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t8D1107310486CEB800E47090 /* Randomify-Info.plist */,\n\t\t\t\t089C165CFE840E0CC02AAC07 /* InfoPlist.strings */,\n\t\t\t\t1DDD58140DA1D0A300B32029 /* MainMenu.xib */,\n\t\t\t);\n\t\t\tname = Resources;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t29B97323FDCFA39411CA2CEA /* Frameworks */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t0575227A1161F3A5003FFC9D /* libspotify.framework */,\n\t\t\t\t1058C7A1FEA54F0111CA2CBB /* Cocoa.framework */,\n\t\t\t\t057526E0116248D4003FFC9D /* AudioToolbox.framework */,\n\t\t\t);\n\t\t\tname = Frameworks;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n/* End PBXGroup section */\n\n/* Begin PBXNativeTarget section */\n\t\t8D1107260486CEB800E47090 /* Randomify */ = {\n\t\t\tisa = PBXNativeTarget;\n\t\t\tbuildConfigurationList = C01FCF4A08A954540054247B /* Build configuration list for PBXNativeTarget \"Randomify\" */;\n\t\t\tbuildPhases = (\n\t\t\t\t0575226B1161F20D003FFC9D /* Copy Frameworks */,\n\t\t\t\t8D1107290486CEB800E47090 /* Resources */,\n\t\t\t\t8D11072C0486CEB800E47090 /* Sources */,\n\t\t\t\t8D11072E0486CEB800E47090 /* Frameworks */,\n\t\t\t);\n\t\t\tbuildRules = (\n\t\t\t);\n\t\t\tdependencies = (\n\t\t\t);\n\t\t\tname = Randomify;\n\t\t\tproductInstallPath = \"$(HOME)/Applications\";\n\t\t\tproductName = Randomify;\n\t\t\tproductReference = 8D1107320486CEB800E47090 /* Randomify.app */;\n\t\t\tproductType = \"com.apple.product-type.application\";\n\t\t};\n/* End PBXNativeTarget section */\n\n/* Begin PBXProject section */\n\t\t29B97313FDCFA39411CA2CEA /* Project object */ = {\n\t\t\tisa = PBXProject;\n\t\t\tbuildConfigurationList = C01FCF4E08A954540054247B /* Build configuration list for PBXProject \"Randomify\" */;\n\t\t\tcompatibilityVersion = \"Xcode 3.1\";\n\t\t\thasScannedForEncodings = 1;\n\t\t\tmainGroup = 29B97314FDCFA39411CA2CEA /* Randomify */;\n\t\t\tprojectDirPath = \"\";\n\t\t\tprojectRoot = \"\";\n\t\t\ttargets = (\n\t\t\t\t8D1107260486CEB800E47090 /* Randomify */,\n\t\t\t);\n\t\t};\n/* End PBXProject section */\n\n/* Begin PBXResourcesBuildPhase section */\n\t\t8D1107290486CEB800E47090 /* Resources */ = {\n\t\t\tisa = PBXResourcesBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\t8D11072B0486CEB800E47090 /* InfoPlist.strings in Resources */,\n\t\t\t\t1DDD58160DA1D0A300B32029 /* MainMenu.xib in Resources */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n/* End PBXResourcesBuildPhase section */\n\n/* Begin PBXSourcesBuildPhase section */\n\t\t8D11072C0486CEB800E47090 /* Sources */ = {\n\t\t\tisa = PBXSourcesBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\t8D11072D0486CEB800E47090 /* main.m in Sources */,\n\t\t\t\t256AC3DA0F4B6AC300CF3369 /* RandomifyAppDelegate.m in Sources */,\n\t\t\t\t057522901161F4AE003FFC9D /* appkey.c in Sources */,\n\t\t\t\t057522BB1161F629003FFC9D /* audio.c in Sources */,\n\t\t\t\t057522C01161F6F7003FFC9D /* SpotifySession.m in Sources */,\n\t\t\t\t05752469116225C4003FFC9D /* SpotifyPlaylist.m in Sources */,\n\t\t\t\t057524E11162303B003FFC9D /* SpotifyTrack.m in Sources */,\n\t\t\t\t057526DD116248B1003FFC9D /* osx-audio.c in Sources */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n/* End PBXSourcesBuildPhase section */\n\n/* Begin PBXVariantGroup section */\n\t\t089C165CFE840E0CC02AAC07 /* InfoPlist.strings */ = {\n\t\t\tisa = PBXVariantGroup;\n\t\t\tchildren = (\n\t\t\t\t089C165DFE840E0CC02AAC07 /* English */,\n\t\t\t);\n\t\t\tname = InfoPlist.strings;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t1DDD58140DA1D0A300B32029 /* MainMenu.xib */ = {\n\t\t\tisa = PBXVariantGroup;\n\t\t\tchildren = (\n\t\t\t\t1DDD58150DA1D0A300B32029 /* English */,\n\t\t\t);\n\t\t\tname = MainMenu.xib;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n/* End PBXVariantGroup section */\n\n/* Begin XCBuildConfiguration section */\n\t\tC01FCF4B08A954540054247B /* Debug */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tALWAYS_SEARCH_USER_PATHS = NO;\n\t\t\t\tCOPY_PHASE_STRIP = NO;\n\t\t\t\tFRAMEWORK_SEARCH_PATHS = (\n\t\t\t\t\t\"$(inherited)\",\n\t\t\t\t\t\"\\\"$(SRCROOT)/../..\\\"\",\n\t\t\t\t);\n\t\t\t\tGCC_DYNAMIC_NO_PIC = NO;\n\t\t\t\tGCC_ENABLE_FIX_AND_CONTINUE = YES;\n\t\t\t\tGCC_MODEL_TUNING = G5;\n\t\t\t\tGCC_OPTIMIZATION_LEVEL = 0;\n\t\t\t\tGCC_PRECOMPILE_PREFIX_HEADER = YES;\n\t\t\t\tGCC_PREFIX_HEADER = Randomify_Prefix.pch;\n\t\t\t\tINFOPLIST_FILE = \"Randomify-Info.plist\";\n\t\t\t\tINSTALL_PATH = \"$(HOME)/Applications\";\n\t\t\t\tPRODUCT_NAME = Randomify;\n\t\t\t};\n\t\t\tname = Debug;\n\t\t};\n\t\tC01FCF4C08A954540054247B /* Release */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tALWAYS_SEARCH_USER_PATHS = NO;\n\t\t\t\tDEBUG_INFORMATION_FORMAT = \"dwarf-with-dsym\";\n\t\t\t\tFRAMEWORK_SEARCH_PATHS = (\n\t\t\t\t\t\"$(inherited)\",\n\t\t\t\t\t\"\\\"$(SRCROOT)/../..\\\"\",\n\t\t\t\t);\n\t\t\t\tGCC_MODEL_TUNING = G5;\n\t\t\t\tGCC_PRECOMPILE_PREFIX_HEADER = YES;\n\t\t\t\tGCC_PREFIX_HEADER = Randomify_Prefix.pch;\n\t\t\t\tINFOPLIST_FILE = \"Randomify-Info.plist\";\n\t\t\t\tINSTALL_PATH = \"$(HOME)/Applications\";\n\t\t\t\tPRODUCT_NAME = Randomify;\n\t\t\t};\n\t\t\tname = Release;\n\t\t};\n\t\tC01FCF4F08A954540054247B /* Debug */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tARCHS = \"$(ARCHS_STANDARD_32_64_BIT)\";\n\t\t\t\tGCC_C_LANGUAGE_STANDARD = gnu99;\n\t\t\t\tGCC_OPTIMIZATION_LEVEL = 0;\n\t\t\t\tGCC_WARN_ABOUT_RETURN_TYPE = YES;\n\t\t\t\tGCC_WARN_UNUSED_VARIABLE = YES;\n\t\t\t\tONLY_ACTIVE_ARCH = YES;\n\t\t\t\tPREBINDING = NO;\n\t\t\t\tSDKROOT = macosx10.6;\n\t\t\t};\n\t\t\tname = Debug;\n\t\t};\n\t\tC01FCF5008A954540054247B /* Release */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tARCHS = \"$(ARCHS_STANDARD_32_64_BIT)\";\n\t\t\t\tGCC_C_LANGUAGE_STANDARD = gnu99;\n\t\t\t\tGCC_WARN_ABOUT_RETURN_TYPE = YES;\n\t\t\t\tGCC_WARN_UNUSED_VARIABLE = YES;\n\t\t\t\tPREBINDING = NO;\n\t\t\t\tSDKROOT = macosx10.6;\n\t\t\t};\n\t\t\tname = Release;\n\t\t};\n/* End XCBuildConfiguration section */\n\n/* Begin XCConfigurationList section */\n\t\tC01FCF4A08A954540054247B /* Build configuration list for PBXNativeTarget \"Randomify\" */ = {\n\t\t\tisa = XCConfigurationList;\n\t\t\tbuildConfigurations = (\n\t\t\t\tC01FCF4B08A954540054247B /* Debug */,\n\t\t\t\tC01FCF4C08A954540054247B /* Release */,\n\t\t\t);\n\t\t\tdefaultConfigurationIsVisible = 0;\n\t\t\tdefaultConfigurationName = Release;\n\t\t};\n\t\tC01FCF4E08A954540054247B /* Build configuration list for PBXProject \"Randomify\" */ = {\n\t\t\tisa = XCConfigurationList;\n\t\t\tbuildConfigurations = (\n\t\t\t\tC01FCF4F08A954540054247B /* Debug */,\n\t\t\t\tC01FCF5008A954540054247B /* Release */,\n\t\t\t);\n\t\t\tdefaultConfigurationIsVisible = 0;\n\t\t\tdefaultConfigurationName = Release;\n\t\t};\n/* End XCConfigurationList section */\n\t};\n\trootObject = 29B97313FDCFA39411CA2CEA /* Project object */;\n}\n"
  },
  {
    "path": "libspotify/examples/Randomify/RandomifyAppDelegate.h",
    "content": "/**\n * Copyright (c) 2006-2010 Spotify Ltd\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n *\n *\n * This example application show how to use libspotify in a Mac OS X\n * application, playing randomly from your Starred playlist.\n *\n * This file is part of the libspotify examples suite.\n */\n\n#import <Cocoa/Cocoa.h>\n#import \"SpotifySession.h\"\n\n@interface RandomifyAppDelegate : NSObject\n\t<SpotifySessionDelegate, SpotifyPlaylistDelegate>\n{\n    IBOutlet NSWindow *window;\n\tIBOutlet NSTextField *username;\n\tIBOutlet NSTextField *password;\n\tIBOutlet NSTextField *log;\n\tIBOutlet NSTextField *status;\n\t\n\tSpotifySession *session;\n\tSpotifyPlaylist *starred;\n\tBOOL playing;\n\tIBOutlet NSButton *playButton;\n\t\n\tSpotifyTrack *playingTrack;\n}\n-(IBAction)loginAndPlay:(id)sender;\n\n-(IBAction)playARandomSong:(id)sender;\n-(IBAction)togglePlay:(id)sender;\n@end\n"
  },
  {
    "path": "libspotify/examples/Randomify/RandomifyAppDelegate.m",
    "content": "/**\n * Copyright (c) 2006-2010 Spotify Ltd\n * This file is part of the libspotify examples suite.\n * See RandomifyAppDelegate.h for license.\n */\n\n#import \"RandomifyAppDelegate.h\"\n#import \"SpotifySession.h\"\n\n@interface RandomifyAppDelegate ()\n@property (retain) SpotifyPlaylist *starred;\n@property (retain) SpotifyTrack *playingTrack;\n@property BOOL playing;\n@end\n\n\n@implementation RandomifyAppDelegate\n@synthesize starred, playingTrack;\n#pragma mark Session delegates\n-(void)session:(SpotifySession*)session_ logged:(NSString*)logmsg;\n{\n\tNSString *new = [logmsg stringByAppendingString:log.stringValue];\n\tlog.stringValue = new;\n}\n-(void)sessionLoggedIn:(SpotifySession*)session_ error:(NSError*)err;\n{\n\tif(err) {\n\t\t[NSApp presentError:err];\n\t\treturn;\n\t}\n\t[self session:session logged:@\"Logged in!\\n\"];\n\t\n\tself.starred = session.starred;\n\tstarred.delegate = self;\n\n\t[self playARandomSong:nil];\n}\n-(void)session:(SpotifySession*)session_ connectionError:(NSError*)error;\n{\n\t[NSApp presentError:error];\n}\n-(void)session:(SpotifySession*)session_ streamingError:(NSError*)error;\n{\n\t[NSApp presentError:error];\n}\n\n-(void)playlistEndedUpdating:(SpotifyPlaylist*)playlist;\n{\n\tif(playlist.loaded && !playing)\n\t\t[self playARandomSong:nil];\n}\n-(void)playlistChangedState:(SpotifyPlaylist*)playlist;\n{\n\tif(playlist.loaded && !playing)\n\t\t[self playARandomSong:nil];\n}\n\n-(void)sessionUpdatedMetadata:(SpotifySession *)session_;\n{\n\t// A track we're waiting for metadata for might now have gotten it.\n\tif(!playing && playingTrack && playingTrack.loaded) {\n\t\tif(!playingTrack.available) {\n\t\t\t[self playARandomSong:nil];\n\t\t\treturn;\n\t\t}\n\t\t[self session:session logged:[NSString stringWithFormat:@\"Playing now loaded track: %@\\n\", playingTrack]];\n\t\tstatus.stringValue = playingTrack.description;\n\t\t[session loadTrack:playingTrack];\n\t\t[session play];\n\t\tself.playing = YES;\n\t}\n}\n-(void)sessionEndedPlayingTrack:(SpotifySession*)session_;\n{\n\tself.playing = NO;\n\t[self session:session logged:@\"Playlist is ready!\\n\"];\n\t[self playARandomSong:nil];\n}\n-(void)sessionLostPlayToken:(SpotifySession *)session;\n{\n\tNSRunAlertPanel(@\"Lost play token\", @\"Another client is playing.\", @\"Arrrghh\", nil, nil);\n\tself.playing = NO;\n}\n\n\n#pragma mark -\n- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {\n\tsrandom(time(NULL));\n\tself.playing = NO;\n\n\tNSError *err = nil;\n\tsession = [[SpotifySession alloc] initError:&err];\n\tsession.delegate = self;\n\t\n\tstatus.stringValue = @\"Randomify\";\n\t\n\tif(!session) {\n\t\t[NSApp presentError:err];\n\t\t[NSApp terminate:nil];\n\t}\n}\n-(IBAction)loginAndPlay:(id)sender;\n{\n\t[session loginUser:username.stringValue password:password.stringValue];\n}\n\n-(IBAction)playARandomSong:(id)sender;\n{\n\tNSUInteger count = [starred countOfTracks];\n\n\tif(!starred.loaded || !count) {\n\t\t[self session:session logged:@\"Waiting for playlist to load...\\n\"];\n\t\treturn;\n\t}\n\t\n\tNSUInteger randomIndex = random()%count;\n\t\n\tself.playingTrack = [starred objectInTracksAtIndex:randomIndex];\n\tif(!self.playingTrack.loaded) {\n\t\t[self session:session logged:@\"Waiting for track to load...\\n\"];\n\t\tstatus.stringValue = @\"Loading…\";\n\t\treturn;\n\t}\n\t\n\t[self session:session logged:[NSString stringWithFormat:@\"Playing track: %@\\n\", playingTrack]];\n\tstatus.stringValue = playingTrack.description;\n\t\n\t[session loadTrack:playingTrack];\n\t[session play];\n\n\tself.playing = YES;\n}\n-(IBAction)togglePlay:(id)sender;\n{\n\tif(playing) {\n\t\t[session pause];\n\t\tself.playing = NO;\n\t} else {\n\t\t[session play];\n\t\tself.playing = YES;\n\t}\n}\n\n-(BOOL)playing;\n{\n\treturn playing;\n}\n-(void)setPlaying:(BOOL)playing_;\n{\n\t[playButton setEnabled:playingTrack != nil];\n\t\n\tplaying = playing_;\n\t[playButton setStringValue:playing ? @\"║\" : @\"▹\"];\n}\n@end\n"
  },
  {
    "path": "libspotify/examples/Randomify/SpotifyPlaylist.h",
    "content": "/**\n * Copyright (c) 2006-2010 Spotify Ltd\n * This file is part of the libspotify examples suite.\n * See RandomifyAppDelegate.h for license.\n */\n \n#import <Foundation/Foundation.h>\n#import <libspotify/api.h>\n#import \"SpotifyTrack.h\"\n\n@class SpotifyPlaylist;\n@protocol SpotifyPlaylistDelegate\n@optional\n-(void)playlistBeganUpdating:(SpotifyPlaylist*)playlist;\n-(void)playlistEndedUpdating:(SpotifyPlaylist*)playlist;\n-(void)playlistChangedState:(SpotifyPlaylist*)playlist;\n@end\n\n\n@interface SpotifyPlaylist : NSObject {\n\tsp_playlist *playlist;\n\tsp_playlist_callbacks callbacks;\n\tsp_session *session;\n\tNSObject<SpotifyPlaylistDelegate> *delegate;\n}\n-(id)initWithPlaylist:(sp_playlist*)playlist_ onSession:(sp_session*)sess;\n@property (assign) NSObject<SpotifyPlaylistDelegate> *delegate;\n@property (readonly) BOOL loaded; // listen to playlistEndedUpdating if false\n\n-(NSUInteger)countOfTracks;\n-(SpotifyTrack*)objectInTracksAtIndex:(NSUInteger)index;\n@end\n"
  },
  {
    "path": "libspotify/examples/Randomify/SpotifyPlaylist.m",
    "content": "/**\n * Copyright (c) 2006-2010 Spotify Ltd\n * This file is part of the libspotify examples suite.\n * See RandomifyAppDelegate.h for license.\n */\n\n#import \"SpotifyPlaylist.h\"\n#import \"SpotifyTrack.h\"\n\n#define plobj ((SpotifyPlaylist*)userdata)\n\nstatic void playlist_update_in_progress(sp_playlist *pl, bool done, void *userdata)\n{\n\tif(!done) {\n\t\tif([plobj.delegate respondsToSelector:@selector(playlistBeganUpdating:)])\n\t\t\t[plobj.delegate playlistBeganUpdating:plobj];\n\t} else {\n\t\tif([plobj.delegate respondsToSelector:@selector(playlistEndedUpdating:)])\n\t\t\t[plobj.delegate playlistEndedUpdating:plobj];\n\t}\n}\nstatic void playlist_state_changed(sp_playlist *pl, void *userdata)\n{\n\tif([plobj.delegate respondsToSelector:@selector(playlistChangedState:)])\n\t\t[plobj.delegate playlistChangedState:plobj];\t\n}\n\n// TODO: Instead of exposing playlist content changes as delegate methods,\n// make tracks KVO-compliant\n\n@implementation SpotifyPlaylist\n@synthesize delegate;\n-(id)initWithPlaylist:(sp_playlist*)playlist_ onSession:(sp_session*)sess;\n{\n\tplaylist = playlist_;\n\t\n\tsession = sess;\n\t\n\tcallbacks = (sp_playlist_callbacks) {\n\t\t.playlist_update_in_progress = playlist_update_in_progress,\n\t};\n\t\n\tsp_playlist_add_ref(playlist);\n\tsp_playlist_add_callbacks(playlist, &callbacks, self);\n\t\n\t\n\treturn self;\n}\n-(void)dealloc;\n{\n\tsp_playlist_remove_callbacks(playlist, &callbacks, self);\n\tsp_playlist_release(playlist);\n\t[super dealloc];\n}\n\n-(BOOL)loaded;\n{\n\treturn sp_playlist_is_loaded(playlist);\n}\n-(NSUInteger)countOfTracks;\n{\n\treturn sp_playlist_num_tracks(playlist);\n}\n-(SpotifyTrack*)objectInTracksAtIndex:(NSUInteger)index;\n{\n\treturn [[[SpotifyTrack alloc] initWithTrack:sp_playlist_track(playlist, index) onSession:session] autorelease];\n}\n@end\n"
  },
  {
    "path": "libspotify/examples/Randomify/SpotifySession.h",
    "content": "/**\n * Copyright (c) 2006-2010 Spotify Ltd\n * This file is part of the libspotify examples suite.\n * See RandomifyAppDelegate.h for license.\n */\n\n#import <Foundation/Foundation.h>\n#import <libspotify/api.h>\n#import \"audio.h\"\n#import \"SpotifyPlaylist.h\"\n\n@class SpotifySession;\n@protocol SpotifySessionDelegate\n@optional\n-(void)sessionLoggedIn:(SpotifySession*)session error:(NSError*)err;\n-(void)sessionLoggedOut:(SpotifySession*)session;\n-(void)sessionUpdatedMetadata:(SpotifySession*)session;\n-(void)session:(SpotifySession*)session connectionError:(NSError*)error;\n-(void)session:(SpotifySession*)session hasMessageToUser:(NSString*)message;\n-(void)sessionLostPlayToken:(SpotifySession*)session;\n-(void)session:(SpotifySession*)session logged:(NSString*)logmsg;\n-(void)sessionEndedPlayingTrack:(SpotifySession*)session;\n-(void)session:(SpotifySession*)session streamingError:(NSError*)error;\n-(void)sessionUpdatedUserinfo:(SpotifySession*)session;\n@end\n\n\n@interface SpotifySession : NSObject {\n\tsp_session_config config;\n\tsp_session_callbacks callbacks;\n\tNSString *cachesDir, *supportDir;\n\taudio_fifo_t audiofifo;\n\tsp_session *session;\n\tNSObject<SpotifySessionDelegate> *delegate;\n}\n@property (assign) NSObject<SpotifySessionDelegate> *delegate;\n-(id)initError:(NSError**)err;\n-(void)loginUser:(NSString*)user password:(NSString*)passwd;\n-(void)logout;\n\n@property (readonly) SpotifyPlaylist *starred;\n\n// Should be its own class: SpotifyPlayer\n-(void)loadTrack:(SpotifyTrack*)track;\n-(void)pause;\n-(void)play;\n\n\n// Stops processing events. If you only release this object,\n// the runtime will still own it.\n-(void)shutdown;\n@end\n"
  },
  {
    "path": "libspotify/examples/Randomify/SpotifySession.m",
    "content": "/**\n * Copyright (c) 2006-2010 Spotify Ltd\n * This file is part of the libspotify examples suite.\n * See RandomifyAppDelegate.h for license.\n */\n\n#import \"SpotifySession.h\"\n\n/// The application key is specific to each project, and allows Spotify\n/// to produce statistics on how our service is used.\nextern const uint8_t g_appkey[];\n/// The size of the application key.\nextern const size_t g_appkey_size;\n\nNSError *makeError(sp_error code) {\n\tNSError *err = [NSError errorWithDomain:@\"com.spotify\" code:code userInfo:[NSDictionary dictionaryWithObjectsAndKeys:\n\t\t[NSString stringWithUTF8String:sp_error_message(code)], NSLocalizedDescriptionKey,\n\t\tnil\n\t]];\n\treturn err;\n}\n\n@interface SpotifySession ()\n-(void)processEvents;\n@property (readonly) audio_fifo_t *audiofifo;\n\n-(void)tellDelegateThatSessionLogged:(NSString*)msg;\n\n@end\n\n#pragma mark \n#pragma mark Callbacks\n#pragma mark -\n\nstatic SpotifySession *sessobj(sp_session *session) {\n\treturn (SpotifySession*)sp_session_userdata(session);\n}\n\nstatic void logged_in(sp_session *session, sp_error error)\n{\n\tNSObject<SpotifySessionDelegate> *delegate = sessobj(session).delegate;\n\tNSError *err = SP_ERROR_OK == error ? nil : makeError(error);\n\tif([delegate respondsToSelector:@selector(sessionLoggedIn:error:)])\n\t\t[delegate sessionLoggedIn:sessobj(session) error:err];\n}\n\nstatic void logged_out(sp_session *session)\n{\n\tNSObject<SpotifySessionDelegate> *delegate = sessobj(session).delegate;\n\tif([delegate respondsToSelector:@selector(sessionLoggedOut:)])\n\t\t[delegate sessionLoggedOut:sessobj(session)];\n}\n\nstatic void metadata_updated(sp_session *session)\n{\n\tNSObject<SpotifySessionDelegate> *delegate = sessobj(session).delegate;\n\tif([delegate respondsToSelector:@selector(sessionUpdatedMetadata:)])\n\t\t[delegate sessionUpdatedMetadata:sessobj(session)];\n}\n\nstatic void connection_error(sp_session *session, sp_error error)\n{\n\tNSObject<SpotifySessionDelegate> *delegate = sessobj(session).delegate;\n\tNSError *err = SP_ERROR_OK == error ? nil : makeError(error);\n\tif([delegate respondsToSelector:@selector(session:connectionError:)])\n\t\t[delegate session:sessobj(session) connectionError:err];\n}\n\nstatic void message_to_user(sp_session *session, const char *message)\n{\n\tNSObject<SpotifySessionDelegate> *delegate = sessobj(session).delegate;\n\tNSString *msg = [NSString stringWithUTF8String:message];\n\tif([delegate respondsToSelector:@selector(session:hasMessageToUser:)])\n\t\t[delegate session:sessobj(session) hasMessageToUser:msg];\n}\n\nstatic void notify_main_thread(sp_session *session)\n{\n\t[sessobj(session) performSelectorOnMainThread:@selector(processEvents) withObject:nil waitUntilDone:NO];\n}\n\nstatic int music_delivery(sp_session *sess, const sp_audioformat *format,\n                          const void *frames, int num_frames)\n{\n\taudio_fifo_t *af = sessobj(sess).audiofifo;\n\taudio_fifo_data_t *afd = NULL;\n\tsize_t s;\n\n\tif (num_frames == 0)\n\t\treturn 0; // Audio discontinuity, do nothing\n\n\tpthread_mutex_lock(&af->mutex);\n\n\t/* Buffer one second of audio */\n\tif (af->qlen > format->sample_rate) {\n\t\tpthread_mutex_unlock(&af->mutex);\n\n\t\treturn 0;\n\t}\n\n\ts = num_frames * sizeof(int16_t) * format->channels;\n\n\tafd = malloc(sizeof(audio_fifo_data_t) + s);\n\tmemcpy(afd->samples, frames, s);\n\n\tafd->nsamples = num_frames;\n\n\tafd->rate = format->sample_rate;\n\tafd->channels = format->channels;\n\n\tTAILQ_INSERT_TAIL(&af->q, afd, link);\n\taf->qlen += num_frames;\n\n\tpthread_cond_signal(&af->cond);\n\tpthread_mutex_unlock(&af->mutex);\n\n\treturn num_frames;\n}\n\nstatic void play_token_lost(sp_session *session)\n{\n\tNSObject<SpotifySessionDelegate> *delegate = sessobj(session).delegate;\n\tif([delegate respondsToSelector:@selector(sessionLostPlayToken:)])\n\t\t[delegate sessionLostPlayToken:sessobj(session)];\n}\n\nstatic void log_message(sp_session *session, const char *message)\n{\n\tNSObject<SpotifySessionDelegate> *delegate = sessobj(session).delegate;\n\tNSString *msg = [[NSString alloc] initWithUTF8String:message];\n\tif([delegate respondsToSelector:@selector(session:logged:)])\n\t\t[sessobj(session) performSelectorOnMainThread:@selector(tellDelegateThatSessionLogged:)\n\t\t\t\t\t\t\t\t\t\t   withObject:msg \n\t\t\t\t\t\t\t\t\t\twaitUntilDone:NO];\n\t\n}\n\nstatic void end_of_track(sp_session *session)\n{\n\tNSObject<SpotifySessionDelegate> *delegate = sessobj(session).delegate;\n\tif([delegate respondsToSelector:@selector(sessionEndedPlayingTrack:)])\n\t\t[delegate performSelectorOnMainThread:@selector(sessionEndedPlayingTrack:)\n\t\t\t\t\t\t\t\t   withObject:sessobj(session)\n\t\t\t\t\t\t\t\twaitUntilDone:NO];\n}\n\nstatic void streaming_error(sp_session *session, sp_error error)\n{\n\tNSObject<SpotifySessionDelegate> *delegate = sessobj(session).delegate;\n\tNSError *err = SP_ERROR_OK == error ? nil : makeError(error);\n\tif([delegate respondsToSelector:@selector(session:streamingError:)])\n\t\t[delegate session:sessobj(session) streamingError:err];\n}\n\nstatic void userinfo_updated(sp_session *session)\n{\n\tNSObject<SpotifySessionDelegate> *delegate = sessobj(session).delegate;\n\tif([delegate respondsToSelector:@selector(sessionUpdatedUserinfo:)])\n\t\t[delegate sessionUpdatedUserinfo:sessobj(session)];\n}\n\n\n\n\n#pragma mark  \n@implementation SpotifySession\n#pragma mark -\n@synthesize delegate;\n\n-(id)initError:(NSError**)error;\n{\n\taudio_init(&audiofifo);\n\t\n\tNSArray *cachesDirs = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);\n\tNSArray *supportDirs = NSSearchPathForDirectoriesInDomains(NSApplicationSupportDirectory, NSUserDomainMask, YES);\n\tcachesDir = [[cachesDirs objectAtIndex:0] retain];\n\tsupportDir = [[supportDirs objectAtIndex:0] retain];\n\t\n\tcallbacks = (sp_session_callbacks){\n\t\t.logged_in = logged_in,\n\t\t.logged_out = logged_out,\n\t\t.metadata_updated = metadata_updated,\n\t\t.connection_error = connection_error,\n\t\t.message_to_user = message_to_user,\n\t\t.notify_main_thread = notify_main_thread,\n\t\t.music_delivery = music_delivery,\n\t\t.play_token_lost = play_token_lost,\n\t\t.log_message = log_message,\n\t\t.end_of_track = end_of_track,\n\t\t.streaming_error = streaming_error,\n\t\t.userinfo_updated = userinfo_updated,\n\t};\n\t\n\tconfig = (sp_session_config){\n\t\t.api_version = SPOTIFY_API_VERSION,\n\t\t.cache_location = [cachesDir UTF8String],\n\t\t.settings_location = [supportDir UTF8String],\n\t\t.application_key = g_appkey,\n\t\t.application_key_size = g_appkey_size,\n\t\t.user_agent = [[[NSProcessInfo processInfo] processName] UTF8String],\n\t\t.callbacks = &callbacks,\n\t\t.userdata = self,\n\t};\n\t\n\tsp_error sperror = sp_session_create(&config, &session);\n\t\n\tif (SP_ERROR_OK != sperror) {\n\t\tif(error) *error = makeError(sperror);\n\t\t[self release];\n\t\treturn nil;\n\t}\n\t\n\t[self processEvents];\n\n\t\n\treturn self;\n}\n-(void)dealloc;\n{\n\t// todo: shutdown audiofifo\n\t[cachesDir release];\n\t[supportDir release];\n\t[super dealloc];\n}\n-(void)shutdown;\n{\n\t[NSObject cancelPreviousPerformRequestsWithTarget:self]; // Cancel any pending processEvents\n}\n\n-(void)loginUser:(NSString*)user password:(NSString*)passwd;\n{\n\tsp_session_login(session, [user UTF8String], [passwd UTF8String], 0, NULL);\n}\n-(void)logout;\n{\n\tsp_session_logout(session);\n}\n\n-(SpotifyPlaylist*)starred;\n{\n\tsp_playlist *pl = sp_session_starred_create(session);\n\tSpotifyPlaylist *playlist = [[[SpotifyPlaylist alloc] initWithPlaylist:pl onSession:session] autorelease];\n\tsp_playlist_release(pl);\n\treturn playlist;\n}\n\n-(void)loadTrack:(SpotifyTrack *)track;\n{\n\tsp_session_player_load(session, track.track);\n}\n-(void)pause;\n{\n\taudio_fifo_flush(&audiofifo);\n\tsp_session_player_play(session, FALSE);\n}\n-(void)play;\n{\n\taudio_fifo_flush(&audiofifo);\n\tsp_session_player_play(session, TRUE);\n}\n\n#pragma mark \n#pragma mark Private\n#pragma mark -\n-(void)processEvents;\n{\n\t[NSObject cancelPreviousPerformRequestsWithTarget:self selector:_cmd object:nil];\n\tint msTilNext = 0;\n\twhile(msTilNext == 0)\n\t\tsp_session_process_events(session, &msTilNext);\n\t\n\t\n\tNSTimeInterval secsTilNext = msTilNext/1000.;\n\t[self performSelector:_cmd withObject:nil afterDelay:secsTilNext];\n}\n\n-(audio_fifo_t*)audiofifo;\n{\n\treturn &audiofifo;\n}\n\n-(void)tellDelegateThatSessionLogged:(NSString*)msg;\n{\n\t[delegate session:self logged:msg];\n\t[msg release];\n}\n\n@end\n"
  },
  {
    "path": "libspotify/examples/Randomify/SpotifyTrack.h",
    "content": "/**\n * Copyright (c) 2006-2010 Spotify Ltd\n * This file is part of the libspotify examples suite.\n * See RandomifyAppDelegate.h for license.\n */\n\n#import <Foundation/Foundation.h>\n#import <libspotify/api.h>\n\n@interface SpotifyTrack : NSObject {\n\tsp_track *track;\n\tsp_session *session;\n}\n-(id)initWithTrack:(sp_track*)track_ onSession:(sp_session*)sess;\n\n@property (readonly) NSString *name;\n@property (readonly) NSString *artistName;\n@property (readonly) BOOL loaded;\n@property (readonly) BOOL available;\n\n// Private\n@property (readonly) sp_track *track;\n@end\n"
  },
  {
    "path": "libspotify/examples/Randomify/SpotifyTrack.m",
    "content": "/**\n * Copyright (c) 2006-2010 Spotify Ltd\n * This file is part of the libspotify examples suite.\n * See RandomifyAppDelegate.h for license.\n */\n\n#import \"SpotifyTrack.h\"\n\n\n@implementation SpotifyTrack\n@synthesize track;\n-(id)initWithTrack:(sp_track*)track_ onSession:(sp_session*)sess;\n{\n\ttrack = track_;\n\tsession = sess;\n\tsp_track_add_ref(track);\n\treturn self;\n}\n-(void)dealloc;\n{\n\tsp_track_release(track);\n\t[super dealloc];\n}\n\n-(NSString*)name;\n{\n\tconst char *name = sp_track_name(track);\n\tif(!name || !sp_track_is_loaded(track)) return @\"[loading]\";\n\treturn [NSString stringWithUTF8String:sp_track_name(track)];\n}\n-(NSString*)artistName;\n{\n\tsp_artist *artist = sp_track_artist(track, 0);\n\tconst char *artistName = artist ? sp_artist_name(artist) : \"[loading]\";\n\treturn [NSString stringWithUTF8String:artistName];\n}\n-(BOOL)loaded;\n{\n\treturn sp_track_is_loaded(track);\n}\n-(BOOL)available;\n{\n\treturn sp_track_get_availability(session, track) == SP_TRACK_AVAILABILITY_AVAILABLE;\n}\n\n-(NSString*)description;\n{\n\treturn [NSString stringWithFormat:@\"<%@ by %@>\",\n\t\tself.name,\n\t\tself.artistName\n\t];\n}\n\n@end\n"
  },
  {
    "path": "libspotify/examples/Randomify/main.m",
    "content": "//\n//  main.m\n//  Randomify\n//\n//  Created by Joachim Bengtsson on 2010-03-30.\n//  Copyright 2010 Spotify. All rights reserved.\n//\n\n#import <Cocoa/Cocoa.h>\n\nint main(int argc, char *argv[])\n{\n    return NSApplicationMain(argc,  (const char **) argv);\n}\n"
  },
  {
    "path": "libspotify/examples/appkey.c",
    "content": "#error\n#error \"You need to replace this file with a libspotify API key provided by Spotify. Please see https://developer.spotify.com/en/libspotify/application-key/\"\n#error\n"
  },
  {
    "path": "libspotify/examples/common.mk",
    "content": "# Copyright (c) 2010 Spotify Ltd\n\nall:\tcheck-libspotify $(TARGET)\n\n#\n# Direct path to libspotify\n#\nifdef LIBSPOTIFY_PATH\n\nP=$(shell cd \"$(LIBSPOTIFY_PATH)\" && pwd)\n\ncheck-libspotify:\n\t@test -f $(P)/lib/libspotify.so || (echo \"Failed to find libspotify.so in $(P)/lib\" >&2 ; exit 1)\n\t@test -f $(P)/include/libspotify/api.h || (echo \"Failed to find libspotify/api.h in $(P)/include\" >&2 ; exit 1)\n\nCFLAGS  += -I$(P)/include\nLDFLAGS += -Wl,-rpath,$(P)/lib -L$(P)/lib\nLDLIBS  += -lspotify\n\nifeq ($(shell uname),Darwin)\nCPUARCH   ?= $(shell uname -m)\nCFLAGS    += -D__APPLE__ -arch $(CPUARCH)\nLDFLAGS   += -arch $(CPUARCH)\nendif\n\n#\n# Use pkg-config(1)\n#\nelse\n\ncheck-libspotify:\n\t@pkg-config --exists libspotify || (echo \"Failed to find libspotify using pkg-config(1)\" >&2 ; exit 1)\n\nCFLAGS  += $(shell PKG_CONFIG_PATH=$(PKG_CONFIG_PATH) pkg-config --cflags libspotify)\nLDFLAGS += $(shell PKG_CONFIG_PATH=$(PKG_CONFIG_PATH) pkg-config --libs-only-L libspotify)\nLDLIBS  += $(shell PKG_CONFIG_PATH=$(PKG_CONFIG_PATH) pkg-config --libs-only-l --libs-only-other libspotify)\n\nendif\n\nifdef DEBUG\nCFLAGS += -g3 -O0\nendif\n\nCFLAGS += -Wall\n\n.PHONY: all check-libspotify clean\n\nvpath %.c ../\n\nclean:\n\trm -f *.o *~ $(TARGET)\n"
  },
  {
    "path": "libspotify/examples/jukebox/Makefile",
    "content": "ifeq ($(shell uname),Darwin)\nifdef USE_AUDIOQUEUE\nAUDIO_DRIVER ?= osx\nLDFLAGS += -framework AudioToolbox\nelse\nAUDIO_DRIVER ?= openal\nLDFLAGS += -framework OpenAL\nendif\nelse\nCFLAGS  = $(shell PKG_CONFIG_PATH=$(PKG_CONFIG_PATH) pkg-config --cflags alsa)\nLDFLAGS = $(shell PKG_CONFIG_PATH=$(PKG_CONFIG_PATH) pkg-config --libs-only-L alsa)\nLDLIBS  = $(shell PKG_CONFIG_PATH=$(PKG_CONFIG_PATH) pkg-config --libs-only-l --libs-only-other alsa)\nAUDIO_DRIVER ?= alsa\nendif\n\nTARGET = jukebox\n## TARGET = playtrack\nOBJS = $(TARGET).o appkey.o $(AUDIO_DRIVER)-audio.o audio.o\n\n$(TARGET): $(OBJS)\n\t$(CC) $(CFLAGS) $(LDFLAGS) $^ -o $@ $(LDLIBS)\nifdef DEBUG\nifeq ($(shell uname),Darwin)\n\tinstall_name_tool -change @loader_path/../Frameworks/libspotify.framework/libspotify @rpath/libspotify.so $@\nendif\nendif\n\ninclude ../common.mk\n\n\n\naudio.o: audio.c audio.h\nalsa-audio.o: alsa-audio.c audio.h\ndummy-audio.o: dummy-audio.c audio.h\nosx-audio.o: osx-audio.c audio.h\nopenal-audio.o: openal-audio.c audio.h\njukebox.o: jukebox.c audio.h\nplaytrack.o: playtrack.c audio.h\n"
  },
  {
    "path": "libspotify/examples/jukebox/alsa-audio.c",
    "content": "/*\n * Copyright (c) 2006-2009 Spotify Ltd\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n *\n *\n * ALSA audio output driver.\n *\n * This file is part of the libspotify examples suite.\n */\n\n#include <asoundlib.h>\n#include <errno.h>\n#include <math.h>\n#include <stdio.h>\n#include <stdlib.h>\n#include <unistd.h>\n#include <sys/time.h>\n\n#include \"audio.h\"\n\n\nstatic snd_pcm_t *alsa_open(char *dev, int rate, int channels)\n{\n\tsnd_pcm_hw_params_t *hwp;\n\tsnd_pcm_sw_params_t *swp;\n\tsnd_pcm_t *h;\n\tint r;\n\tint dir;\n\tsnd_pcm_uframes_t period_size_min;\n\tsnd_pcm_uframes_t period_size_max;\n\tsnd_pcm_uframes_t buffer_size_min;\n\tsnd_pcm_uframes_t buffer_size_max;\n\tsnd_pcm_uframes_t period_size;\n\tsnd_pcm_uframes_t buffer_size;\n\n\tif ((r = snd_pcm_open(&h, dev, SND_PCM_STREAM_PLAYBACK, 0) < 0))\n\t\treturn NULL;\n\n\thwp = alloca(snd_pcm_hw_params_sizeof());\n\tmemset(hwp, 0, snd_pcm_hw_params_sizeof());\n\tsnd_pcm_hw_params_any(h, hwp);\n\n\tsnd_pcm_hw_params_set_access(h, hwp, SND_PCM_ACCESS_RW_INTERLEAVED);\n\tsnd_pcm_hw_params_set_format(h, hwp, SND_PCM_FORMAT_S16_LE);\n\tsnd_pcm_hw_params_set_rate(h, hwp, rate, 0);\n\tsnd_pcm_hw_params_set_channels(h, hwp, channels);\n\n\t/* Configurue period */\n\n\tdir = 0;\n\tsnd_pcm_hw_params_get_period_size_min(hwp, &period_size_min, &dir);\n\tdir = 0;\n\tsnd_pcm_hw_params_get_period_size_max(hwp, &period_size_max, &dir);\n\n\tperiod_size = 1024;\n\n\tdir = 0;\n\tr = snd_pcm_hw_params_set_period_size_near(h, hwp, &period_size, &dir);\n\n\tif (r < 0) {\n\t\tfprintf(stderr, \"audio: Unable to set period size %lu (%s)\\n\",\n\t\t        period_size, snd_strerror(r));\n\t\tsnd_pcm_close(h);\n\t\treturn NULL;\n\t}\n\n\tdir = 0;\n\tr = snd_pcm_hw_params_get_period_size(hwp, &period_size, &dir);\n\n\tif (r < 0) {\n\t\tfprintf(stderr, \"audio: Unable to get period size (%s)\\n\",\n\t\t        snd_strerror(r));\n\t\tsnd_pcm_close(h);\n\t\treturn NULL;\n\t}\n\n\t/* Configurue buffer size */\n\n\tsnd_pcm_hw_params_get_buffer_size_min(hwp, &buffer_size_min);\n\tsnd_pcm_hw_params_get_buffer_size_max(hwp, &buffer_size_max);\n\tbuffer_size = period_size * 4;\n\n\tdir = 0;\n\tr = snd_pcm_hw_params_set_buffer_size_near(h, hwp, &buffer_size);\n\n\tif (r < 0) {\n\t\tfprintf(stderr, \"audio: Unable to set buffer size %lu (%s)\\n\",\n\t\t        buffer_size, snd_strerror(r));\n\t\tsnd_pcm_close(h);\n\t\treturn NULL;\n\t}\n\n\tr = snd_pcm_hw_params_get_buffer_size(hwp, &buffer_size);\n\n\tif (r < 0) {\n\t\tfprintf(stderr, \"audio: Unable to get buffer size (%s)\\n\",\n\t\t        snd_strerror(r));\n\t\tsnd_pcm_close(h);\n\t\treturn NULL;\n\t}\n\n\t/* write the hw params */\n\tr = snd_pcm_hw_params(h, hwp);\n\n\tif (r < 0) {\n\t\tfprintf(stderr, \"audio: Unable to configure hardware parameters (%s)\\n\",\n\t\t        snd_strerror(r));\n\t\tsnd_pcm_close(h);\n\t\treturn NULL;\n\t}\n\n\t/*\n\t * Software parameters\n\t */\n\n\tswp = alloca(snd_pcm_sw_params_sizeof());\n\tmemset(hwp, 0, snd_pcm_sw_params_sizeof());\n\tsnd_pcm_sw_params_current(h, swp);\n\n\tr = snd_pcm_sw_params_set_avail_min(h, swp, period_size);\n\n\tif (r < 0) {\n\t\tfprintf(stderr, \"audio: Unable to configure wakeup threshold (%s)\\n\",\n\t\t        snd_strerror(r));\n\t\tsnd_pcm_close(h);\n\t\treturn NULL;\n\t}\n\n\tsnd_pcm_sw_params_set_start_threshold(h, swp, 0);\n\n\tif (r < 0) {\n\t\tfprintf(stderr, \"audio: Unable to configure start threshold (%s)\\n\",\n\t\t        snd_strerror(r));\n\t\tsnd_pcm_close(h);\n\t\treturn NULL;\n\t}\n\n\tr = snd_pcm_sw_params(h, swp);\n\n\tif (r < 0) {\n\t\tfprintf(stderr, \"audio: Cannot set soft parameters (%s)\\n\",\n\t\tsnd_strerror(r));\n\t\tsnd_pcm_close(h);\n\t\treturn NULL;\n\t}\n\n\tr = snd_pcm_prepare(h);\n\tif (r < 0) {\n\t\tfprintf(stderr, \"audio: Cannot prepare audio for playback (%s)\\n\",\n\t\tsnd_strerror(r));\n\t\tsnd_pcm_close(h);\n\t\treturn NULL;\n\t}\n\n\treturn h;\n}\n\nstatic void* alsa_audio_start(void *aux)\n{\n\taudio_fifo_t *af = aux;\n\tsnd_pcm_t *h = NULL;\n\tint c;\n\tint cur_channels = 0;\n\tint cur_rate = 0;\n\n\taudio_fifo_data_t *afd;\n\n\tfor (;;) {\n\t\tafd = audio_get(af);\n\n\t\tif (!h || cur_rate != afd->rate || cur_channels != afd->channels) {\n\t\t\tif (h) snd_pcm_close(h);\n\n\t\t\tcur_rate = afd->rate;\n\t\t\tcur_channels = afd->channels;\n\n\t\t\th = alsa_open(\"default\", cur_rate, cur_channels);\n\n\t\t\tif (!h) {\n\t\t\t\tfprintf(stderr, \"Unable to open ALSA device (%d channels, %d Hz), dying\\n\",\n\t\t\t\t        cur_channels, cur_rate);\n\t\t\t\texit(1);\n\t\t\t}\n\t\t}\n\n\t\tc = snd_pcm_wait(h, 1000);\n\n\t\tif (c >= 0)\n\t\t\tc = snd_pcm_avail_update(h);\n\n\t\tif (c == -EPIPE)\n\t\t\tsnd_pcm_prepare(h);\n\n\t\tsnd_pcm_writei(h, afd->samples, afd->nsamples);\n\t\tfree(afd);\n\t}\n}\n\nvoid audio_init(audio_fifo_t *af)\n{\n\tpthread_t tid;\n\n\tTAILQ_INIT(&af->q);\n\taf->qlen = 0;\n\n\tpthread_mutex_init(&af->mutex, NULL);\n\tpthread_cond_init(&af->cond, NULL);\n\n\tpthread_create(&tid, NULL, alsa_audio_start, af);\n}\n\n"
  },
  {
    "path": "libspotify/examples/jukebox/audio.c",
    "content": "/*\n * Copyright (c) 2010 Spotify Ltd\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n *\n *\n * Audio helper functions.\n *\n * This file is part of the libspotify examples suite.\n */\n\n#include \"audio.h\"\n#include <stdlib.h>\n\naudio_fifo_data_t* audio_get(audio_fifo_t *af)\n{\n    audio_fifo_data_t *afd;\n    pthread_mutex_lock(&af->mutex);\n  \n    while (!(afd = TAILQ_FIRST(&af->q)))\n\tpthread_cond_wait(&af->cond, &af->mutex);\n  \n    TAILQ_REMOVE(&af->q, afd, link);\n    af->qlen -= afd->nsamples;\n  \n    pthread_mutex_unlock(&af->mutex);\n    return afd;\n}\n\nvoid audio_fifo_flush(audio_fifo_t *af)\n{\n    audio_fifo_data_t *afd;\n\n\n    pthread_mutex_lock(&af->mutex);\n\n    while((afd = TAILQ_FIRST(&af->q))) {\n\tTAILQ_REMOVE(&af->q, afd, link);\n\tfree(afd);\n    }\n\n    af->qlen = 0;\n    pthread_mutex_unlock(&af->mutex);\n}\n"
  },
  {
    "path": "libspotify/examples/jukebox/audio.h",
    "content": "/*\n * Copyright (c) 2006-2009 Spotify Ltd\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n *\n *\n * Audio output driver.\n *\n * This file is part of the libspotify examples suite.\n */\n#ifndef _JUKEBOX_AUDIO_H_\n#define _JUKEBOX_AUDIO_H_\n\n#include <pthread.h>\n#include <stdint.h>\n#include \"queue.h\"\n\n\n/* --- Types --- */\ntypedef struct audio_fifo_data {\n\tTAILQ_ENTRY(audio_fifo_data) link;\n\tint channels;\n\tint rate;\n\tint nsamples;\n\tint16_t samples[0];\n} audio_fifo_data_t;\n\ntypedef struct audio_fifo {\n\tTAILQ_HEAD(, audio_fifo_data) q;\n\tint qlen;\n\tpthread_mutex_t mutex;\n\tpthread_cond_t cond;\n} audio_fifo_t;\n\n\n/* --- Functions --- */\nextern void audio_init(audio_fifo_t *af);\nextern void audio_fifo_flush(audio_fifo_t *af);\naudio_fifo_data_t* audio_get(audio_fifo_t *af);\n\n#endif /* _JUKEBOX_AUDIO_H_ */\n"
  },
  {
    "path": "libspotify/examples/jukebox/dummy-audio.c",
    "content": "/*\n * Copyright (c) 2006-2009 Spotify Ltd\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n *\n *\n * ALSA audio output driver.\n *\n * This file is part of the libspotify examples suite.\n */\n\n#include <asoundlib.h>\n#include <errno.h>\n#include <math.h>\n#include <stdio.h>\n#include <stdlib.h>\n#include <unistd.h>\n#include <sys/time.h>\n\n#include \"audio.h\"\n\nstatic void* alsa_audio_start(void *aux)\n{\n\taudio_fifo_t *af = aux;\n\n\twhile(1)\n\t\tfree(audio_get(af));\n\treturn NULL;\n}\n\nvoid audio_init(audio_fifo_t *af)\n{\n\tpthread_t tid;\n\n\tTAILQ_INIT(&af->q);\n\taf->qlen = 0;\n\n\tpthread_mutex_init(&af->mutex, NULL);\n\tpthread_cond_init(&af->cond, NULL);\n\n\tpthread_create(&tid, NULL, alsa_audio_start, af);\n}\n\n\n"
  },
  {
    "path": "libspotify/examples/jukebox/jukebox.c",
    "content": "/**\n * Copyright (c) 2006-2010 Spotify Ltd\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n *\n *\n * This example application shows parts of the playlist and player submodules.\n * It also shows another way of doing synchronization between callbacks and\n * the main thread.\n *\n * This file is part of the libspotify examples suite.\n */\n\n#include <errno.h>\n#include <libgen.h>\n#include <pthread.h>\n#include <stdint.h>\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n#include <unistd.h>\n#include <sys/time.h>\n\n#include <libspotify/api.h>\n\n#include \"audio.h\"\n\n\n/* --- Data --- */\n/// The application key is specific to each project, and allows Spotify\n/// to produce statistics on how our service is used.\nextern const uint8_t g_appkey[];\n/// The size of the application key.\nextern const size_t g_appkey_size;\n\n/// The output queue for audo data\nstatic audio_fifo_t g_audiofifo;\n/// Synchronization mutex for the main thread\nstatic pthread_mutex_t g_notify_mutex;\n/// Synchronization condition variable for the main thread\nstatic pthread_cond_t g_notify_cond;\n/// Synchronization variable telling the main thread to process events\nstatic int g_notify_do;\n/// Non-zero when a track has ended and the jukebox has not yet started a new one\nstatic int g_playback_done;\n/// The global session handle\nstatic sp_session *g_sess;\n/// Handle to the playlist currently being played\nstatic sp_playlist *g_jukeboxlist;\n/// Name of the playlist currently being played\nconst char *g_listname;\n/// Remove tracks flag\nstatic int g_remove_tracks = 0;\n/// Handle to the curren track\nstatic sp_track *g_currenttrack;\n/// Index to the next track\nstatic int g_track_index;\n\n\n/**\n * Called on various events to start playback if it hasn't been started already.\n *\n * The function simply starts playing the first track of the playlist.\n */\nstatic void try_jukebox_start(void)\n{\n\tsp_track *t;\n\n\tif (!g_jukeboxlist)\n\t\treturn;\n\n\tif (!sp_playlist_num_tracks(g_jukeboxlist)) {\n\t\tfprintf(stderr, \"jukebox: No tracks in playlist. Waiting\\n\");\n\t\treturn;\n\t}\n\n\tif (sp_playlist_num_tracks(g_jukeboxlist) < g_track_index) {\n\t\tfprintf(stderr, \"jukebox: No more tracks in playlist. Waiting\\n\");\n\t\treturn;\n\t}\n\n\tt = sp_playlist_track(g_jukeboxlist, g_track_index);\n\n\tif (g_currenttrack && t != g_currenttrack) {\n\t\t/* Someone changed the current track */\n\t\taudio_fifo_flush(&g_audiofifo);\n\t\tsp_session_player_unload(g_sess);\n\t\tg_currenttrack = NULL;\n\t}\n\n\tif (!t)\n\t\treturn;\n\n\tif (sp_track_error(t) != SP_ERROR_OK)\n\t\treturn;\n\n\tif (g_currenttrack == t)\n\t\treturn;\n\n\tg_currenttrack = t;\n\n\tprintf(\"jukebox: Now playing \\\"%s\\\"...\\n\", sp_track_name(t));\n\tfflush(stdout);\n\n\tsp_session_player_load(g_sess, t);\n\tsp_session_player_play(g_sess, 1);\n}\n\n/* --------------------------  PLAYLIST CALLBACKS  ------------------------- */\n/**\n * Callback from libspotify, saying that a track has been added to a playlist.\n *\n * @param  pl          The playlist handle\n * @param  tracks      An array of track handles\n * @param  num_tracks  The number of tracks in the \\c tracks array\n * @param  position    Where the tracks were inserted\n * @param  userdata    The opaque pointer\n */\nstatic void tracks_added(sp_playlist *pl, sp_track * const *tracks,\n                         int num_tracks, int position, void *userdata)\n{\n\tif (pl != g_jukeboxlist)\n\t\treturn;\n\n\tprintf(\"jukebox: %d tracks were added\\n\", num_tracks);\n\tfflush(stdout);\n\ttry_jukebox_start();\n}\n\n/**\n * Callback from libspotify, saying that a track has been added to a playlist.\n *\n * @param  pl          The playlist handle\n * @param  tracks      An array of track indices\n * @param  num_tracks  The number of tracks in the \\c tracks array\n * @param  userdata    The opaque pointer\n */\nstatic void tracks_removed(sp_playlist *pl, const int *tracks,\n                           int num_tracks, void *userdata)\n{\n\tint i, k = 0;\n\n\tif (pl != g_jukeboxlist)\n\t\treturn;\n\n\tfor (i = 0; i < num_tracks; ++i)\n\t\tif (tracks[i] < g_track_index)\n\t\t\t++k;\n\n\tg_track_index -= k;\n\n\tprintf(\"jukebox: %d tracks were removed\\n\", num_tracks);\n\tfflush(stdout);\n\ttry_jukebox_start();\n}\n\n/**\n * Callback from libspotify, telling when tracks have been moved around in a playlist.\n *\n * @param  pl            The playlist handle\n * @param  tracks        An array of track indices\n * @param  num_tracks    The number of tracks in the \\c tracks array\n * @param  new_position  To where the tracks were moved\n * @param  userdata      The opaque pointer\n */\nstatic void tracks_moved(sp_playlist *pl, const int *tracks,\n                         int num_tracks, int new_position, void *userdata)\n{\n\tif (pl != g_jukeboxlist)\n\t\treturn;\n\n\tprintf(\"jukebox: %d tracks were moved around\\n\", num_tracks);\n\tfflush(stdout);\n\ttry_jukebox_start();\n}\n\n/**\n * Callback from libspotify. Something renamed the playlist.\n *\n * @param  pl            The playlist handle\n * @param  userdata      The opaque pointer\n */\nstatic void playlist_renamed(sp_playlist *pl, void *userdata)\n{\n\tconst char *name = sp_playlist_name(pl);\n\n\tif (!strcasecmp(name, g_listname)) {\n\t\tg_jukeboxlist = pl;\n\t\tg_track_index = 0;\n\t\ttry_jukebox_start();\n\t} else if (g_jukeboxlist == pl) {\n\t\tprintf(\"jukebox: current playlist renamed to \\\"%s\\\".\\n\", name);\n\t\tg_jukeboxlist = NULL;\n\t\tg_currenttrack = NULL;\n\t\tsp_session_player_unload(g_sess);\n\t}\n}\n\n/**\n * The callbacks we are interested in for individual playlists.\n */\nstatic sp_playlist_callbacks pl_callbacks = {\n\t.tracks_added = &tracks_added,\n\t.tracks_removed = &tracks_removed,\n\t.tracks_moved = &tracks_moved,\n\t.playlist_renamed = &playlist_renamed,\n};\n\n\n/* --------------------  PLAYLIST CONTAINER CALLBACKS  --------------------- */\n/**\n * Callback from libspotify, telling us a playlist was added to the playlist container.\n *\n * We add our playlist callbacks to the newly added playlist.\n *\n * @param  pc            The playlist container handle\n * @param  pl            The playlist handle\n * @param  position      Index of the added playlist\n * @param  userdata      The opaque pointer\n */\nstatic void playlist_added(sp_playlistcontainer *pc, sp_playlist *pl,\n                           int position, void *userdata)\n{\n\tsp_playlist_add_callbacks(pl, &pl_callbacks, NULL);\n\n\tif (!strcasecmp(sp_playlist_name(pl), g_listname)) {\n\t\tg_jukeboxlist = pl;\n\t\ttry_jukebox_start();\n\t}\n}\n\n/**\n * Callback from libspotify, telling us a playlist was removed from the playlist container.\n *\n * This is the place to remove our playlist callbacks.\n *\n * @param  pc            The playlist container handle\n * @param  pl            The playlist handle\n * @param  position      Index of the removed playlist\n * @param  userdata      The opaque pointer\n */\nstatic void playlist_removed(sp_playlistcontainer *pc, sp_playlist *pl,\n                             int position, void *userdata)\n{\n\tsp_playlist_remove_callbacks(pl, &pl_callbacks, NULL);\n}\n\n\n/**\n * Callback from libspotify, telling us the rootlist is fully synchronized\n * We just print an informational message\n *\n * @param  pc            The playlist container handle\n * @param  userdata      The opaque pointer\n */\nstatic void container_loaded(sp_playlistcontainer *pc, void *userdata)\n{\n\tfprintf(stderr, \"jukebox: Rootlist synchronized (%d playlists)\\n\",\n\t    sp_playlistcontainer_num_playlists(pc));\n}\n\n\n/**\n * The playlist container callbacks\n */\nstatic sp_playlistcontainer_callbacks pc_callbacks = {\n\t.playlist_added = &playlist_added,\n\t.playlist_removed = &playlist_removed,\n\t.container_loaded = &container_loaded,\n};\n\n\n/* ---------------------------  SESSION CALLBACKS  ------------------------- */\n/**\n * This callback is called when an attempt to login has succeeded or failed.\n *\n * @sa sp_session_callbacks#logged_in\n */\nstatic void logged_in(sp_session *sess, sp_error error)\n{\n\tsp_playlistcontainer *pc = sp_session_playlistcontainer(sess);\n\tint i;\n\n\tif (SP_ERROR_OK != error) {\n\t\tfprintf(stderr, \"jukebox: Login failed: %s\\n\",\n\t\t\tsp_error_message(error));\n\t\texit(2);\n\t}\n\n\tsp_playlistcontainer_add_callbacks(\n\t\tpc,\n\t\t&pc_callbacks,\n\t\tNULL);\n\n\tprintf(\"jukebox: Looking at %d playlists\\n\", sp_playlistcontainer_num_playlists(pc));\n\n\tfor (i = 0; i < sp_playlistcontainer_num_playlists(pc); ++i) {\n\t\tsp_playlist *pl = sp_playlistcontainer_playlist(pc, i);\n\n\t\tsp_playlist_add_callbacks(pl, &pl_callbacks, NULL);\n\n\t\tif (!strcasecmp(sp_playlist_name(pl), g_listname)) {\n\t\t\tg_jukeboxlist = pl;\n\t\t\ttry_jukebox_start();\n\t\t}\n\t}\n\n\tif (!g_jukeboxlist) {\n\t\tprintf(\"jukebox: No such playlist. Waiting for one to pop up...\\n\");\n\t\tfflush(stdout);\n\t}\n}\n\n/**\n * This callback is called from an internal libspotify thread to ask us to\n * reiterate the main loop.\n *\n * We notify the main thread using a condition variable and a protected variable.\n *\n * @sa sp_session_callbacks#notify_main_thread\n */\nstatic void notify_main_thread(sp_session *sess)\n{\n\tpthread_mutex_lock(&g_notify_mutex);\n\tg_notify_do = 1;\n\tpthread_cond_signal(&g_notify_cond);\n\tpthread_mutex_unlock(&g_notify_mutex);\n}\n\n/**\n * This callback is used from libspotify whenever there is PCM data available.\n *\n * @sa sp_session_callbacks#music_delivery\n */\nstatic int music_delivery(sp_session *sess, const sp_audioformat *format,\n                          const void *frames, int num_frames)\n{\n\taudio_fifo_t *af = &g_audiofifo;\n\taudio_fifo_data_t *afd;\n\tsize_t s;\n\n\tif (num_frames == 0)\n\t\treturn 0; // Audio discontinuity, do nothing\n\n\tpthread_mutex_lock(&af->mutex);\n\n\t/* Buffer one second of audio */\n\tif (af->qlen > format->sample_rate) {\n\t\tpthread_mutex_unlock(&af->mutex);\n\n\t\treturn 0;\n\t}\n\n\ts = num_frames * sizeof(int16_t) * format->channels;\n\n\tafd = malloc(sizeof(*afd) + s);\n\tmemcpy(afd->samples, frames, s);\n\n\tafd->nsamples = num_frames;\n\n\tafd->rate = format->sample_rate;\n\tafd->channels = format->channels;\n\n\tTAILQ_INSERT_TAIL(&af->q, afd, link);\n\taf->qlen += num_frames;\n\n\tpthread_cond_signal(&af->cond);\n\tpthread_mutex_unlock(&af->mutex);\n\n\treturn num_frames;\n}\n\n\n/**\n * This callback is used from libspotify when the current track has ended\n *\n * @sa sp_session_callbacks#end_of_track\n */\nstatic void end_of_track(sp_session *sess)\n{\n\tpthread_mutex_lock(&g_notify_mutex);\n\tg_playback_done = 1;\n\tg_notify_do = 1;\n\tpthread_cond_signal(&g_notify_cond);\n\tpthread_mutex_unlock(&g_notify_mutex);\n}\n\n\n/**\n * Callback called when libspotify has new metadata available\n *\n * Not used in this example (but available to be able to reuse the session.c file\n * for other examples.)\n *\n * @sa sp_session_callbacks#metadata_updated\n */\nstatic void metadata_updated(sp_session *sess)\n{\n\ttry_jukebox_start();\n}\n\n/**\n * Notification that some other connection has started playing on this account.\n * Playback has been stopped.\n *\n * @sa sp_session_callbacks#play_token_lost\n */\nstatic void play_token_lost(sp_session *sess)\n{\n\taudio_fifo_flush(&g_audiofifo);\n\n\tif (g_currenttrack != NULL) {\n\t\tsp_session_player_unload(g_sess);\n\t\tg_currenttrack = NULL;\n\t}\n}\n\n/**\n * The session callbacks\n */\nstatic sp_session_callbacks session_callbacks = {\n\t.logged_in = &logged_in,\n\t.notify_main_thread = &notify_main_thread,\n\t.music_delivery = &music_delivery,\n\t.metadata_updated = &metadata_updated,\n\t.play_token_lost = &play_token_lost,\n\t.log_message = NULL,\n\t.end_of_track = &end_of_track,\n};\n\n/**\n * The session configuration. Note that application_key_size is an external, so\n * we set it in main() instead.\n */\nstatic sp_session_config spconfig = {\n\t.api_version = SPOTIFY_API_VERSION,\n\t.cache_location = \"tmp\",\n\t.settings_location = \"tmp\",\n\t.application_key = g_appkey,\n\t.application_key_size = 0, // Set in main()\n\t.user_agent = \"spotify-jukebox-example\",\n\t.callbacks = &session_callbacks,\n\tNULL,\n};\n/* -------------------------  END SESSION CALLBACKS  ----------------------- */\n\n\n/**\n * A track has ended. Remove it from the playlist.\n *\n * Called from the main loop when the music_delivery() callback has set g_playback_done.\n */\nstatic void track_ended(void)\n{\n\tint tracks = 0;\n\n\tif (g_currenttrack) {\n\t\tg_currenttrack = NULL;\n\t\tsp_session_player_unload(g_sess);\n\t\tif (g_remove_tracks) {\n\t\t\tsp_playlist_remove_tracks(g_jukeboxlist, &tracks, 1);\n\t\t} else {\n\t\t\t++g_track_index;\n\t\t\ttry_jukebox_start();\n\t\t}\n\t}\n}\n\n/**\n * Show usage information\n *\n * @param  progname  The program name\n */\nstatic void usage(const char *progname)\n{\n\tfprintf(stderr, \"usage: %s -u <username> -p <password> -l <listname> [-d]\\n\", progname);\n\tfprintf(stderr, \"warning: -d will delete the tracks played from the list!\\n\");\n}\n\nint main(int argc, char **argv)\n{\n\tsp_session *sp;\n\tsp_error err;\n\tint next_timeout = 0;\n\tconst char *username = NULL;\n\tconst char *password = NULL;\n\tint opt;\n\n\twhile ((opt = getopt(argc, argv, \"u:p:l:d\")) != EOF) {\n\t\tswitch (opt) {\n\t\tcase 'u':\n\t\t\tusername = optarg;\n\t\t\tbreak;\n\n\t\tcase 'p':\n\t\t\tpassword = optarg;\n\t\t\tbreak;\n\n\t\tcase 'l':\n\t\t\tg_listname = optarg;\n\t\t\tbreak;\n\n\t\tcase 'd':\n\t\t\tg_remove_tracks = 1;\n\t\t\tbreak;\n\n\t\tdefault:\n\t\t\texit(1);\n\t\t}\n\t}\n\n\tif (!username || !password || !g_listname) {\n\t\tusage(basename(argv[0]));\n\t\texit(1);\n\t}\n\n\taudio_init(&g_audiofifo);\n\n\t/* Create session */\n\tspconfig.application_key_size = g_appkey_size;\n\n\terr = sp_session_create(&spconfig, &sp);\n\n\tif (SP_ERROR_OK != err) {\n\t\tfprintf(stderr, \"Unable to create session: %s\\n\",\n\t\t\tsp_error_message(err));\n\t\texit(1);\n\t}\n\n\tg_sess = sp;\n\n\tpthread_mutex_init(&g_notify_mutex, NULL);\n\tpthread_cond_init(&g_notify_cond, NULL);\n\n\tsp_session_login(sp, username, password, 0, NULL);\n\tpthread_mutex_lock(&g_notify_mutex);\n\n\tfor (;;) {\n\t\tif (next_timeout == 0) {\n\t\t\twhile(!g_notify_do)\n\t\t\t\tpthread_cond_wait(&g_notify_cond, &g_notify_mutex);\n\t\t} else {\n\t\t\tstruct timespec ts;\n\n#if _POSIX_TIMERS > 0\n\t\t\tclock_gettime(CLOCK_REALTIME, &ts);\n#else\n\t\t\tstruct timeval tv;\n\t\t\tgettimeofday(&tv, NULL);\n\t\t\tTIMEVAL_TO_TIMESPEC(&tv, &ts);\n#endif\n\t\t\tts.tv_sec += next_timeout / 1000;\n\t\t\tts.tv_nsec += (next_timeout % 1000) * 1000000;\n\n\t\t\tpthread_cond_timedwait(&g_notify_cond, &g_notify_mutex, &ts);\n\t\t}\n\n\t\tg_notify_do = 0;\n\t\tpthread_mutex_unlock(&g_notify_mutex);\n\n\t\tif (g_playback_done) {\n\t\t\ttrack_ended();\n\t\t\tg_playback_done = 0;\n\t\t}\n\n\t\tdo {\n\t\t\tsp_session_process_events(sp, &next_timeout);\n\t\t} while (next_timeout == 0);\n\n\t\tpthread_mutex_lock(&g_notify_mutex);\n\t}\n\n\treturn 0;\n}\n"
  },
  {
    "path": "libspotify/examples/jukebox/openal-audio.c",
    "content": "/*\n * Copyright (c) 2010 Spotify Ltd\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n *\n *\n * OpenAL audio output driver.\n *\n * This file is part of the libspotify examples suite.\n */\n\n#include <OpenAL/al.h>\n#include <OpenAL/alc.h>\n#include <errno.h>\n#include <math.h>\n#include <stdio.h>\n#include <stdlib.h>\n#include <unistd.h>\n#include <sys/time.h>\n\n#include \"audio.h\"\n\n#define NUM_BUFFERS 3\n\nstatic void error_exit(const char *msg)\n{\n    puts(msg);\n    exit(1);\n}\n\nstatic int queue_buffer(ALuint source, audio_fifo_t *af, ALuint buffer)\n{\n    audio_fifo_data_t *afd = audio_get(af);\n    alBufferData(buffer, \n\t\t afd->channels == 1 ? AL_FORMAT_MONO16 : AL_FORMAT_STEREO16, \n\t\t afd->samples, \n\t\t afd->nsamples * afd->channels * sizeof(short), \n\t\t afd->rate);\n    alSourceQueueBuffers(source, 1, &buffer);\n\tfree(afd);\n\treturn 1;\n}\n\nstatic void* audio_start(void *aux)\n{\n\taudio_fifo_t *af = aux;\n    audio_fifo_data_t *afd;\n\tunsigned int frame = 0;\n\tALCdevice *device = NULL;\n\tALCcontext *context = NULL;\n\tALuint buffers[NUM_BUFFERS];\n\tALuint source;\n\tALint processed;\n\tALenum error;\n\tALint rate;\n\tALint channels;\n\tdevice = alcOpenDevice(NULL); /* Use the default device */\n\tif (!device) error_exit(\"failed to open device\");\n\tcontext = alcCreateContext(device, NULL);\n\talcMakeContextCurrent(context);\n\talListenerf(AL_GAIN, 1.0f);\n\talDistanceModel(AL_NONE);\n\talGenBuffers((ALsizei)NUM_BUFFERS, buffers);\n\talGenSources(1, &source);\n\n\t/* First prebuffer some audio */\n\tqueue_buffer(source, af, buffers[0]);\n\tqueue_buffer(source, af, buffers[1]);\n\tqueue_buffer(source, af, buffers[2]);\n\tfor (;;) {\n      \n\t\talSourcePlay(source);\n\t\tfor (;;) {\n\t\t\t/* Wait for some audio to play */\n\t\t\tdo {\n\t\t\t\talGetSourcei(source, AL_BUFFERS_PROCESSED, &processed);\n\t\t\t\tusleep(100);\n\t\t\t} while (!processed);\n\t\t\t\n\t\t\t/* Remove old audio from the queue.. */\n\t\t\talSourceUnqueueBuffers(source, 1, &buffers[frame % 3]);\n\t\t\t\n\t\t\t/* and queue some more audio */\n\t\t\tafd = audio_get(af);\n\t\t\talGetBufferi(buffers[frame % 3], AL_FREQUENCY, &rate);\n\t\t\talGetBufferi(buffers[frame % 3], AL_CHANNELS, &channels);\n\t\t\tif (afd->rate != rate || afd->channels != channels) {\n\t\t\t\tprintf(\"rate or channel count changed, resetting\\n\");\n                                free(afd);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\talBufferData(buffers[frame % 3], \n\t\t\t\t\t\t afd->channels == 1 ? AL_FORMAT_MONO16 : AL_FORMAT_STEREO16, \n\t\t\t\t\t\t afd->samples, \n\t\t\t\t\t\t afd->nsamples * afd->channels * sizeof(short), \n\t\t\t\t\t\t afd->rate);\n                        free(afd);\n\t\t\talSourceQueueBuffers(source, 1, &buffers[frame % 3]);\n\t\t\t\n\t\t\tif ((error = alcGetError(device)) != AL_NO_ERROR) {\n\t\t\t\tprintf(\"openal al error: %d\\n\", error);\n\t\t\t\texit(1);\n\t\t\t}\n\t\t\tframe++;\n\t\t}\n\t\t/* Format or rate changed, so we need to reset all buffers */\n\t\talSourcei(source, AL_BUFFER, 0);\n\t\talSourceStop(source);\n\n\t\t/* Make sure we don't lose the audio packet that caused the change */\n\t\talBufferData(buffers[0], \n\t\t\t\t\t afd->channels == 1 ? AL_FORMAT_MONO16 : AL_FORMAT_STEREO16, \n\t\t\t\t\t afd->samples, \n\t\t\t\t\t afd->nsamples * afd->channels * sizeof(short), \n\t\t\t\t\t afd->rate);\n\n\t\talSourceQueueBuffers(source, 1, &buffers[0]);\n\t\tqueue_buffer(source, af, buffers[1]);\n\t\tqueue_buffer(source, af, buffers[2]);\n\t\tframe = 0;\n\t}\n}\n\nvoid audio_init(audio_fifo_t *af)\n{\n    pthread_t tid;\n\n    TAILQ_INIT(&af->q);\n    af->qlen = 0;\n\n    pthread_mutex_init(&af->mutex, NULL);\n    pthread_cond_init(&af->cond, NULL);\n\n    pthread_create(&tid, NULL, audio_start, af);\n}\n\n\n"
  },
  {
    "path": "libspotify/examples/jukebox/osx/jukebox.xcodeproj/project.pbxproj",
    "content": "// !$*UTF8*$!\n{\n\tarchiveVersion = 1;\n\tclasses = {\n\t};\n\tobjectVersion = 45;\n\tobjects = {\n\n/* Begin PBXBuildFile section */\n\t\tCF61ED9F115B641D00443233 /* appkey.c in Sources */ = {isa = PBXBuildFile; fileRef = CF61ED99115B641D00443233 /* appkey.c */; };\n\t\tCF61EDA0115B641D00443233 /* audio.c in Sources */ = {isa = PBXBuildFile; fileRef = CF61ED9A115B641D00443233 /* audio.c */; };\n\t\tCF61EDA1115B641D00443233 /* jukebox.c in Sources */ = {isa = PBXBuildFile; fileRef = CF61ED9C115B641D00443233 /* jukebox.c */; };\n\t\tCF61EDA2115B641D00443233 /* openal-audio.c in Sources */ = {isa = PBXBuildFile; fileRef = CF61ED9D115B641D00443233 /* openal-audio.c */; };\n\t\tCF61EDA6115B644A00443233 /* libspotify.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CF61EDA5115B644A00443233 /* libspotify.framework */; };\n\t\tCF61EDB0115B647B00443233 /* OpenAL.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CF61EDAF115B647B00443233 /* OpenAL.framework */; };\n/* End PBXBuildFile section */\n\n/* Begin PBXFileReference section */\n\t\t8DD76FB20486AB0100D96B5E /* jukebox */ = {isa = PBXFileReference; explicitFileType = \"compiled.mach-o.executable\"; includeInIndex = 0; path = jukebox; sourceTree = BUILT_PRODUCTS_DIR; };\n\t\tCF61ED99115B641D00443233 /* appkey.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = appkey.c; path = ../../appkey.c; sourceTree = SOURCE_ROOT; };\n\t\tCF61ED9A115B641D00443233 /* audio.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = audio.c; path = ../audio.c; sourceTree = SOURCE_ROOT; };\n\t\tCF61ED9B115B641D00443233 /* audio.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = audio.h; path = ../audio.h; sourceTree = SOURCE_ROOT; };\n\t\tCF61ED9C115B641D00443233 /* jukebox.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = jukebox.c; path = ../jukebox.c; sourceTree = SOURCE_ROOT; };\n\t\tCF61ED9D115B641D00443233 /* openal-audio.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = \"openal-audio.c\"; path = \"../openal-audio.c\"; sourceTree = SOURCE_ROOT; };\n\t\tCF61ED9E115B641D00443233 /* queue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = queue.h; path = ../queue.h; sourceTree = SOURCE_ROOT; };\n\t\tCF61EDA5115B644A00443233 /* libspotify.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = libspotify.framework; path = /Library/Frameworks/libspotify.framework; sourceTree = \"<absolute>\"; };\n\t\tCF61EDAF115B647B00443233 /* OpenAL.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = OpenAL.framework; path = System/Library/Frameworks/OpenAL.framework; sourceTree = SDKROOT; };\n/* End PBXFileReference section */\n\n/* Begin PBXFrameworksBuildPhase section */\n\t\t8DD76FAD0486AB0100D96B5E /* Frameworks */ = {\n\t\t\tisa = PBXFrameworksBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\tCF61EDA6115B644A00443233 /* libspotify.framework in Frameworks */,\n\t\t\t\tCF61EDB0115B647B00443233 /* OpenAL.framework in Frameworks */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n/* End PBXFrameworksBuildPhase section */\n\n/* Begin PBXGroup section */\n\t\t08FB7794FE84155DC02AAC07 /* jukebox */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t08FB7795FE84155DC02AAC07 /* Source */,\n\t\t\t\t1AB674ADFE9D54B511CA2CBB /* Products */,\n\t\t\t\tCF61EDA5115B644A00443233 /* libspotify.framework */,\n\t\t\t\tCF61EDAF115B647B00443233 /* OpenAL.framework */,\n\t\t\t);\n\t\t\tname = jukebox;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t08FB7795FE84155DC02AAC07 /* Source */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\tCF61ED99115B641D00443233 /* appkey.c */,\n\t\t\t\tCF61ED9A115B641D00443233 /* audio.c */,\n\t\t\t\tCF61ED9B115B641D00443233 /* audio.h */,\n\t\t\t\tCF61ED9C115B641D00443233 /* jukebox.c */,\n\t\t\t\tCF61ED9D115B641D00443233 /* openal-audio.c */,\n\t\t\t\tCF61ED9E115B641D00443233 /* queue.h */,\n\t\t\t);\n\t\t\tname = Source;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t1AB674ADFE9D54B511CA2CBB /* Products */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t8DD76FB20486AB0100D96B5E /* jukebox */,\n\t\t\t);\n\t\t\tname = Products;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n/* End PBXGroup section */\n\n/* Begin PBXNativeTarget section */\n\t\t8DD76FA90486AB0100D96B5E /* jukebox */ = {\n\t\t\tisa = PBXNativeTarget;\n\t\t\tbuildConfigurationList = 1DEB928508733DD80010E9CD /* Build configuration list for PBXNativeTarget \"jukebox\" */;\n\t\t\tbuildPhases = (\n\t\t\t\t057527F21163423F003FFC9D /* ShellScript */,\n\t\t\t\t8DD76FAB0486AB0100D96B5E /* Sources */,\n\t\t\t\t8DD76FAD0486AB0100D96B5E /* Frameworks */,\n\t\t\t\t0575280B11634840003FFC9D /* ShellScript */,\n\t\t\t);\n\t\t\tbuildRules = (\n\t\t\t);\n\t\t\tdependencies = (\n\t\t\t);\n\t\t\tname = jukebox;\n\t\t\tproductInstallPath = \"$(HOME)/bin\";\n\t\t\tproductName = jukebox;\n\t\t\tproductReference = 8DD76FB20486AB0100D96B5E /* jukebox */;\n\t\t\tproductType = \"com.apple.product-type.tool\";\n\t\t};\n/* End PBXNativeTarget section */\n\n/* Begin PBXProject section */\n\t\t08FB7793FE84155DC02AAC07 /* Project object */ = {\n\t\t\tisa = PBXProject;\n\t\t\tbuildConfigurationList = 1DEB928908733DD80010E9CD /* Build configuration list for PBXProject \"jukebox\" */;\n\t\t\tcompatibilityVersion = \"Xcode 3.1\";\n\t\t\thasScannedForEncodings = 1;\n\t\t\tmainGroup = 08FB7794FE84155DC02AAC07 /* jukebox */;\n\t\t\tprojectDirPath = \"\";\n\t\t\tprojectRoot = \"\";\n\t\t\ttargets = (\n\t\t\t\t8DD76FA90486AB0100D96B5E /* jukebox */,\n\t\t\t);\n\t\t};\n/* End PBXProject section */\n\n/* Begin PBXShellScriptBuildPhase section */\n\t\t057527F21163423F003FFC9D /* ShellScript */ = {\n\t\t\tisa = PBXShellScriptBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t);\n\t\t\tinputPaths = (\n\t\t\t);\n\t\t\toutputPaths = (\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t\tshellPath = /bin/bash;\n\t\t\tshellScript = \"if [ ! -e /Library/Frameworks/libspotify.framework ]; then\\n  echo \\\"You must install libspotify.framework to /Library/Frameworks.\\\" >&2\\n  exit 1\\nfi\\n\\nexit 0\";\n\t\t};\n\t\t0575280B11634840003FFC9D /* ShellScript */ = {\n\t\t\tisa = PBXShellScriptBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t);\n\t\t\tinputPaths = (\n\t\t\t);\n\t\t\toutputPaths = (\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t\tshellPath = /bin/sh;\n\t\t\tshellScript = \"install_name_tool -change @loader_path/../Frameworks/libspotify.framework/libspotify /Library/Frameworks/libspotify.framework/libspotify $CONFIGURATION_BUILD_DIR/$EXECUTABLE_PATH\";\n\t\t\tshowEnvVarsInLog = 0;\n\t\t};\n/* End PBXShellScriptBuildPhase section */\n\n/* Begin PBXSourcesBuildPhase section */\n\t\t8DD76FAB0486AB0100D96B5E /* Sources */ = {\n\t\t\tisa = PBXSourcesBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\tCF61ED9F115B641D00443233 /* appkey.c in Sources */,\n\t\t\t\tCF61EDA0115B641D00443233 /* audio.c in Sources */,\n\t\t\t\tCF61EDA1115B641D00443233 /* jukebox.c in Sources */,\n\t\t\t\tCF61EDA2115B641D00443233 /* openal-audio.c in Sources */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n/* End PBXSourcesBuildPhase section */\n\n/* Begin XCBuildConfiguration section */\n\t\t1DEB928608733DD80010E9CD /* Debug */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tALWAYS_SEARCH_USER_PATHS = NO;\n\t\t\t\tCOPY_PHASE_STRIP = NO;\n\t\t\t\tFRAMEWORK_SEARCH_PATHS = (\n\t\t\t\t\t\"$(inherited)\",\n\t\t\t\t\t\"\\\"$(SRCROOT)/../../../..\\\"\",\n\t\t\t\t);\n\t\t\t\tGCC_DYNAMIC_NO_PIC = NO;\n\t\t\t\tGCC_ENABLE_FIX_AND_CONTINUE = YES;\n\t\t\t\tGCC_MODEL_TUNING = G5;\n\t\t\t\tGCC_OPTIMIZATION_LEVEL = 0;\n\t\t\t\tINSTALL_PATH = /usr/local/bin;\n\t\t\t\tPRODUCT_NAME = jukebox;\n\t\t\t};\n\t\t\tname = Debug;\n\t\t};\n\t\t1DEB928708733DD80010E9CD /* Release */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tALWAYS_SEARCH_USER_PATHS = NO;\n\t\t\t\tDEBUG_INFORMATION_FORMAT = \"dwarf-with-dsym\";\n\t\t\t\tFRAMEWORK_SEARCH_PATHS = (\n\t\t\t\t\t\"$(inherited)\",\n\t\t\t\t\t\"\\\"$(SRCROOT)/../../..\\\"\",\n\t\t\t\t);\n\t\t\t\tGCC_MODEL_TUNING = G5;\n\t\t\t\tINSTALL_PATH = /usr/local/bin;\n\t\t\t\tPRODUCT_NAME = jukebox;\n\t\t\t};\n\t\t\tname = Release;\n\t\t};\n\t\t1DEB928A08733DD80010E9CD /* Debug */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tARCHS = \"$(ARCHS_STANDARD_32_64_BIT)\";\n\t\t\t\tGCC_C_LANGUAGE_STANDARD = gnu99;\n\t\t\t\tGCC_OPTIMIZATION_LEVEL = 0;\n\t\t\t\tGCC_WARN_ABOUT_RETURN_TYPE = YES;\n\t\t\t\tGCC_WARN_UNUSED_VARIABLE = YES;\n\t\t\t\tONLY_ACTIVE_ARCH = YES;\n\t\t\t\tPREBINDING = NO;\n\t\t\t\tSDKROOT = macosx10.6;\n\t\t\t};\n\t\t\tname = Debug;\n\t\t};\n\t\t1DEB928B08733DD80010E9CD /* Release */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tARCHS = \"$(ARCHS_STANDARD_32_64_BIT)\";\n\t\t\t\tGCC_C_LANGUAGE_STANDARD = gnu99;\n\t\t\t\tGCC_WARN_ABOUT_RETURN_TYPE = YES;\n\t\t\t\tGCC_WARN_UNUSED_VARIABLE = YES;\n\t\t\t\tPREBINDING = NO;\n\t\t\t\tSDKROOT = macosx10.6;\n\t\t\t};\n\t\t\tname = Release;\n\t\t};\n/* End XCBuildConfiguration section */\n\n/* Begin XCConfigurationList section */\n\t\t1DEB928508733DD80010E9CD /* Build configuration list for PBXNativeTarget \"jukebox\" */ = {\n\t\t\tisa = XCConfigurationList;\n\t\t\tbuildConfigurations = (\n\t\t\t\t1DEB928608733DD80010E9CD /* Debug */,\n\t\t\t\t1DEB928708733DD80010E9CD /* Release */,\n\t\t\t);\n\t\t\tdefaultConfigurationIsVisible = 0;\n\t\t\tdefaultConfigurationName = Release;\n\t\t};\n\t\t1DEB928908733DD80010E9CD /* Build configuration list for PBXProject \"jukebox\" */ = {\n\t\t\tisa = XCConfigurationList;\n\t\t\tbuildConfigurations = (\n\t\t\t\t1DEB928A08733DD80010E9CD /* Debug */,\n\t\t\t\t1DEB928B08733DD80010E9CD /* Release */,\n\t\t\t);\n\t\t\tdefaultConfigurationIsVisible = 0;\n\t\t\tdefaultConfigurationName = Release;\n\t\t};\n/* End XCConfigurationList section */\n\t};\n\trootObject = 08FB7793FE84155DC02AAC07 /* Project object */;\n}\n"
  },
  {
    "path": "libspotify/examples/jukebox/osx-audio.c",
    "content": "/*\n * Copyright (c) 2010 Spotify Ltd\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n *\n *\n * OSX AudioQueue output driver.\n *\n * This file is part of the libspotify examples suite.\n */\n\n#include <AudioToolbox/AudioQueue.h>\n#include \"audio.h\"\n\n#define BUFFER_COUNT 7\nstatic struct AQPlayerState {\n    AudioStreamBasicDescription   desc;\n    AudioQueueRef                 queue;\n    AudioQueueBufferRef           buffers[BUFFER_COUNT];\n    unsigned buffer_size;\n} state;\n\nstatic void audio_callback (void *aux, AudioQueueRef aq, AudioQueueBufferRef bufout)\n{\n    audio_fifo_t *af = aux;\n    audio_fifo_data_t *afd = audio_get(af);\n\n    bufout->mAudioDataByteSize = afd->nsamples * sizeof(short) * afd->channels;\n\n    assert(bufout->mAudioDataByteSize <= state.buffer_size);\n    memcpy(bufout->mAudioData, afd->samples, bufout->mAudioDataByteSize);\n\n    AudioQueueEnqueueBuffer(state.queue, bufout, 0, NULL);\n    free(afd);\n}\n\nstatic const int kSampleCountPerBuffer = 2048;\n\nvoid audio_init(audio_fifo_t *af)\n{\n    int i;\n    TAILQ_INIT(&af->q);\n    af->qlen = 0;\n\n    pthread_mutex_init(&af->mutex, NULL);\n    pthread_cond_init(&af->cond, NULL);\n\n    bzero(&state, sizeof(state));\n\n    state.desc.mFormatID = kAudioFormatLinearPCM;\n    state.desc.mFormatFlags = kAudioFormatFlagIsSignedInteger\t| kAudioFormatFlagIsPacked;\n    state.desc.mSampleRate = 44100;\n    state.desc.mChannelsPerFrame = 2;\n    state.desc.mFramesPerPacket = 1;\n    state.desc.mBytesPerFrame = sizeof(short) * state.desc.mChannelsPerFrame;\n    state.desc.mBytesPerPacket = state.desc.mBytesPerFrame;\n    state.desc.mBitsPerChannel = (state.desc.mBytesPerFrame*8)/state.desc.mChannelsPerFrame;\n    state.desc.mReserved = 0;\n\n    state.buffer_size = state.desc.mBytesPerFrame * kSampleCountPerBuffer;\n\n    if (noErr != AudioQueueNewOutput(&state.desc, audio_callback, af, NULL, NULL, 0, &state.queue)) {\n\tprintf(\"audioqueue error\\n\");\n\treturn;\n    }\n\n    // Start some empty playback so we'll get the callbacks that fill in the actual audio.\n    for (i = 0; i < BUFFER_COUNT; ++i) {\n\t\tAudioQueueAllocateBuffer(state.queue, state.buffer_size, &state.buffers[i]);\n\t\tstate.buffers[i]->mAudioDataByteSize = state.buffer_size;\n\t\tAudioQueueEnqueueBuffer(state.queue, state.buffers[i], 0, NULL);\n    }\n    if (noErr != AudioQueueStart(state.queue, NULL)) puts(\"AudioQueueStart failed\");\n}\n\n"
  },
  {
    "path": "libspotify/examples/jukebox/playtrack.c",
    "content": "/**\n * Copyright (c) 2006-2010 Spotify Ltd\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n *\n *\n * This example application is the most minimal way to just play a spotify URI.\n *\n * This file is part of the libspotify examples suite.\n */\n\n#include <errno.h>\n#include <libgen.h>\n#include <pthread.h>\n#include <stdint.h>\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n#include <unistd.h>\n#include <sys/time.h>\n\n#include <libspotify/api.h>\n\n#include \"audio.h\"\n\n\n/* --- Data --- */\n/// The application key is specific to each project, and allows Spotify\n/// to produce statistics on how our service is used.\nextern const uint8_t g_appkey[];\n/// The size of the application key.\nextern const size_t g_appkey_size;\n\n/// The output queue for audo data\nstatic audio_fifo_t g_audiofifo;\n/// Synchronization mutex for the main thread\nstatic pthread_mutex_t g_notify_mutex;\n/// Synchronization condition variable for the main thread\nstatic pthread_cond_t g_notify_cond;\n/// Synchronization variable telling the main thread to process events\nstatic int g_notify_do;\n/// Non-zero when a track has ended and the jukebox has not yet started a new one\nstatic int g_playback_done;\n/// The global session handle\nstatic sp_session *g_sess;\n/// Handle to the curren track\nstatic sp_track *g_currenttrack;\n\n/* ---------------------------  SESSION CALLBACKS  ------------------------- */\n/**\n * This callback is called when an attempt to login has succeeded or failed.\n *\n * @sa sp_session_callbacks#logged_in\n */\nstatic void logged_in(sp_session *sess, sp_error error)\n{\n\tsp_link *link;\n\n\tif (SP_ERROR_OK != error) {\n\t\tfprintf(stderr, \"Login failed: %s\\n\",\n\t\t\tsp_error_message(error));\n\t\texit(2);\n\t}\n\n\tprintf(\"Loading track\\n\");\n\tlink = sp_link_create_from_string(\"spotify:track:5W3cjX2J3tjhG8zb6u0qHn\");\n        sp_track_add_ref(g_currenttrack = sp_link_as_track(link));\n\tsp_link_release(link);\n\n\tif (sp_track_error(g_currenttrack) == SP_ERROR_OK) {\n\t\tprintf(\"Now playing \\\"%s\\\"...\\n\", sp_track_name(g_currenttrack));\n\t\tfflush(stdout);\n\t\t\n\t\tsp_session_player_load(g_sess, g_currenttrack);\n\t\tsp_session_player_play(g_sess, 1);\n        }\n\n\t/* Track not loaded? Then we need to wait for the metadata to\n           load before we can start playback (see below) */\n}\n\n/**\n * Callback called when libspotify has new metadata available\n *\n * @sa sp_session_callbacks#metadata_updated\n */\nstatic void metadata_updated(sp_session *sess)\n{\n\tputs(\"Metadata updated, trying to start playback\");\n\n\tif (sp_track_error(g_currenttrack) != SP_ERROR_OK)\n\t\treturn;\n\n\tprintf(\"Now playing \\\"%s\\\"...\\n\", sp_track_name(g_currenttrack));\n\tfflush(stdout);\n\n\tsp_session_player_load(g_sess, g_currenttrack);\n\tsp_session_player_play(g_sess, 1);\n}\n\n/**\n * This callback is called from an internal libspotify thread to ask\n * us to reiterate the main loop.\n *\n * We notify the main thread using a condition variable and a protected variable.\n *\n * @sa sp_session_callbacks#notify_main_thread\n */\nstatic void notify_main_thread(sp_session *sess)\n{\n\tpthread_mutex_lock(&g_notify_mutex);\n\tg_notify_do = 1;\n\tpthread_cond_signal(&g_notify_cond);\n\tpthread_mutex_unlock(&g_notify_mutex);\n}\n\n/**\n * This callback is used from libspotify whenever there is PCM data available.\n *\n * @sa sp_session_callbacks#music_delivery\n */\nstatic int music_delivery(sp_session *sess, const sp_audioformat *format,\n                          const void *frames, int num_frames)\n{\n\taudio_fifo_t *af = &g_audiofifo;\n\taudio_fifo_data_t *afd;\n\tsize_t s;\n\n\tif (num_frames == 0)\n\t\treturn 0; // Audio discontinuity, do nothing\n\n\tpthread_mutex_lock(&af->mutex);\n\n\t/* Buffer one second of audio */\n\tif (af->qlen > format->sample_rate) {\n\t\tpthread_mutex_unlock(&af->mutex);\n\n\t\treturn 0;\n\t}\n\n\ts = num_frames * sizeof(int16_t) * format->channels;\n\n\tafd = malloc(sizeof(audio_fifo_data_t) + s);\n\tmemcpy(afd->samples, frames, s);\n\n\tafd->nsamples = num_frames;\n\n\tafd->rate = format->sample_rate;\n\tafd->channels = format->channels;\n\n\tTAILQ_INSERT_TAIL(&af->q, afd, link);\n\taf->qlen += num_frames;\n\n\tpthread_cond_signal(&af->cond);\n\tpthread_mutex_unlock(&af->mutex);\n\n\treturn num_frames;\n}\n\n\n/**\n * This callback is used from libspotify when the current track has ended\n *\n * @sa sp_session_callbacks#end_of_track\n */\nstatic void end_of_track(sp_session *sess)\n{\n\tpthread_mutex_lock(&g_notify_mutex);\n\tg_playback_done = 1;\n\tpthread_cond_signal(&g_notify_cond);\n\tpthread_mutex_unlock(&g_notify_mutex);\n}\n\n/**\n * Notification that some other connection has started playing on this account.\n * Playback has been stopped.\n *\n * @sa sp_session_callbacks#play_token_lost\n */\nstatic void play_token_lost(sp_session *sess)\n{\n\taudio_fifo_flush(&g_audiofifo);\n\n\tif (g_currenttrack != NULL) {\n\t\tsp_session_player_unload(g_sess);\n\t\tg_currenttrack = NULL;\n\t}\n}\n\nstatic void log_message(sp_session *session, const char *msg)\n{\n\tputs(msg);\n}\n\n/**\n * The session callbacks\n */\nstatic sp_session_callbacks session_callbacks = {\n\t.logged_in = &logged_in,\n\t.notify_main_thread = &notify_main_thread,\n\t.music_delivery = &music_delivery,\n\t.metadata_updated = &metadata_updated,\n\t.play_token_lost = &play_token_lost,\n\t.log_message = &log_message,\n\t.end_of_track = &end_of_track,\n};\n\n/**\n * The session configuration. Note that application_key_size is an\n * external, so we set it in main() instead.\n */\nstatic sp_session_config spconfig = {\n\t.api_version = SPOTIFY_API_VERSION,\n\t.cache_location = \"tmp\",\n\t.settings_location = \"tmp\",\n\t.application_key = g_appkey,\n\t.application_key_size = 0, // Set in main()\n\t.user_agent = \"spotify-playtrack-example\",\n\t.callbacks = &session_callbacks,\n\tNULL,\n};\n/* -------------------------  END SESSION CALLBACKS  ----------------------- */\n\n\n/**\n * A track has ended. Remove it from the playlist.\n *\n * Called from the main loop when the music_delivery() callback has set g_playback_done.\n */\nstatic void track_ended(void)\n{\n\tif (g_currenttrack) {\n\t\tsp_track_release(g_currenttrack);\n\t\tg_currenttrack = NULL;\n\t\tsp_session_player_unload(g_sess);\n\t\texit(0);\n\t}\n}\n\n/**\n * Show usage information\n *\n * @param  progname  The program name\n */\nstatic void usage(const char *progname)\n{\n\tfprintf(stderr, \"usage: %s -u <username> -p <password>\\n\", progname);\n}\n\nint main(int argc, char **argv)\n{\n\tsp_session *sp;\n\tsp_error err;\n\tint next_timeout = 0;\n\tconst char *username = NULL;\n\tconst char *password = NULL;\n\tint opt;\n\n\twhile ((opt = getopt(argc, argv, \"u:p:\")) != EOF) {\n\t\tswitch (opt) {\n\t\tcase 'u':\n\t\t\tusername = optarg;\n\t\t\tbreak;\n\t\tcase 'p':\n\t\t\tpassword = optarg;\n\t\t\tbreak;\n\t\tdefault:\n\t\t\texit(1);\n\t\t}\n\t}\n\n\tif (!username || !password) {\n\t\tusage(basename(argv[0]));\n\t\texit(1);\n\t}\n\n\taudio_init(&g_audiofifo);\n\n\t/* Create session */\n\tspconfig.application_key_size = g_appkey_size;\n\n\terr = sp_session_create(&spconfig, &sp);\n\n\tif (SP_ERROR_OK != err) {\n\t\tfprintf(stderr, \"Unable to create session: %s\\n\",\n\t\t\tsp_error_message(err));\n\t\texit(1);\n\t}\n\n\tg_sess = sp;\n\n\tpthread_mutex_init(&g_notify_mutex, NULL);\n\tpthread_cond_init(&g_notify_cond, NULL);\n\n\tsp_session_login(sp, username, password, 0, NULL);\n\tpthread_mutex_lock(&g_notify_mutex);\n\n\tfor (;;) {\n\t\tif (next_timeout == 0) {\n\t\t\twhile(!g_notify_do && !g_playback_done)\n\t\t\t\tpthread_cond_wait(&g_notify_cond, &g_notify_mutex);\n\t\t} else {\n\t\t\tstruct timespec ts;\n\n#if _POSIX_TIMERS > 0\n\t\t\tclock_gettime(CLOCK_REALTIME, &ts);\n#else\n\t\t\tstruct timeval tv;\n\t\t\tgettimeofday(&tv, NULL);\n\t\t\tTIMEVAL_TO_TIMESPEC(&tv, &ts);\n#endif\n\t\t\tts.tv_sec += next_timeout / 1000;\n\t\t\tts.tv_nsec += (next_timeout % 1000) * 1000000;\n\n\t\t\tpthread_cond_timedwait(&g_notify_cond, &g_notify_mutex, &ts);\n\t\t}\n\n\t\tg_notify_do = 0;\n\t\tpthread_mutex_unlock(&g_notify_mutex);\n\n\t\tif (g_playback_done) {\n\t\t\ttrack_ended();\n\t\t\tg_playback_done = 0;\n\t\t}\n\n\t\tdo {\n\t\t\tsp_session_process_events(sp, &next_timeout);\n\t\t} while (next_timeout == 0);\n\n\t\tpthread_mutex_lock(&g_notify_mutex);\n\t}\n\n\treturn 0;\n}\n"
  },
  {
    "path": "libspotify/examples/jukebox/queue.h",
    "content": "/*\n * Copyright (c) 1991, 1993\n *\tThe Regents of the University of California.  All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n * 1. Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n * 2. Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n * 3. Neither the name of the University nor the names of its contributors\n *    may be used to endorse or promote products derived from this software\n *    without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND\n * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE\n * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\n * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS\n * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\n * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT\n * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY\n * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF\n * SUCH DAMAGE.\n *\n *\t@(#)queue.h\t8.5 (Berkeley) 8/20/94\n */\n\n#ifndef\t_SYS_QUEUE_H_\n#define\t_SYS_QUEUE_H_\n\n/*\n * This file defines five types of data structures: singly-linked lists,\n * lists, simple queues, tail queues, and circular queues.\n *\n * A singly-linked list is headed by a single forward pointer. The\n * elements are singly linked for minimum space and pointer manipulation\n * overhead at the expense of O(n) removal for arbitrary elements. New\n * elements can be added to the list after an existing element or at the\n * head of the list.  Elements being removed from the head of the list\n * should use the explicit macro for this purpose for optimum\n * efficiency. A singly-linked list may only be traversed in the forward\n * direction.  Singly-linked lists are ideal for applications with large\n * datasets and few or no removals or for implementing a LIFO queue.\n *\n * A list is headed by a single forward pointer (or an array of forward\n * pointers for a hash table header). The elements are doubly linked\n * so that an arbitrary element can be removed without a need to\n * traverse the list. New elements can be added to the list before\n * or after an existing element or at the head of the list. A list\n * may only be traversed in the forward direction.\n *\n * A simple queue is headed by a pair of pointers, one the head of the\n * list and the other to the tail of the list. The elements are singly\n * linked to save space, so elements can only be removed from the\n * head of the list. New elements can be added to the list after\n * an existing element, at the head of the list, or at the end of the\n * list. A simple queue may only be traversed in the forward direction.\n *\n * A tail queue is headed by a pair of pointers, one to the head of the\n * list and the other to the tail of the list. The elements are doubly\n * linked so that an arbitrary element can be removed without a need to\n * traverse the list. New elements can be added to the list before or\n * after an existing element, at the head of the list, or at the end of\n * the list. A tail queue may be traversed in either direction.\n *\n * A circle queue is headed by a pair of pointers, one to the head of the\n * list and the other to the tail of the list. The elements are doubly\n * linked so that an arbitrary element can be removed without a need to\n * traverse the list. New elements can be added to the list before or after\n * an existing element, at the head of the list, or at the end of the list.\n * A circle queue may be traversed in either direction, but has a more\n * complex end of list detection.\n *\n * For details on the use of these macros, see the queue(3) manual page.\n */\n\n/*\n * List definitions.\n */\n#define\tLIST_HEAD(name, type)\t\t\t\t\t\t\\\nstruct name {\t\t\t\t\t\t\t\t\\\n\tstruct type *lh_first;\t/* first element */\t\t\t\\\n}\n\n#define\tLIST_HEAD_INITIALIZER(head)\t\t\t\t\t\\\n\t{ NULL }\n\n#define\tLIST_ENTRY(type)\t\t\t\t\t\t\\\nstruct {\t\t\t\t\t\t\t\t\\\n\tstruct type *le_next;\t/* next element */\t\t\t\\\n\tstruct type **le_prev;\t/* address of previous next element */\t\\\n}\n\n/*\n * List functions.\n */\n#define\tLIST_INIT(head) do {\t\t\t\t\t\t\\\n\t(head)->lh_first = NULL;\t\t\t\t\t\\\n} while (/*CONSTCOND*/0)\n\n#define\tLIST_INSERT_AFTER(listelm, elm, field) do {\t\t\t\\\n\tif (((elm)->field.le_next = (listelm)->field.le_next) != NULL)\t\\\n\t\t(listelm)->field.le_next->field.le_prev =\t\t\\\n\t\t    &(elm)->field.le_next;\t\t\t\t\\\n\t(listelm)->field.le_next = (elm);\t\t\t\t\\\n\t(elm)->field.le_prev = &(listelm)->field.le_next;\t\t\\\n} while (/*CONSTCOND*/0)\n\n#define\tLIST_INSERT_BEFORE(listelm, elm, field) do {\t\t\t\\\n\t(elm)->field.le_prev = (listelm)->field.le_prev;\t\t\\\n\t(elm)->field.le_next = (listelm);\t\t\t\t\\\n\t*(listelm)->field.le_prev = (elm);\t\t\t\t\\\n\t(listelm)->field.le_prev = &(elm)->field.le_next;\t\t\\\n} while (/*CONSTCOND*/0)\n\n#define\tLIST_INSERT_HEAD(head, elm, field) do {\t\t\t\t\\\n\tif (((elm)->field.le_next = (head)->lh_first) != NULL)\t\t\\\n\t\t(head)->lh_first->field.le_prev = &(elm)->field.le_next;\\\n\t(head)->lh_first = (elm);\t\t\t\t\t\\\n\t(elm)->field.le_prev = &(head)->lh_first;\t\t\t\\\n} while (/*CONSTCOND*/0)\n\n#define\tLIST_REMOVE(elm, field) do {\t\t\t\t\t\\\n\tif ((elm)->field.le_next != NULL)\t\t\t\t\\\n\t\t(elm)->field.le_next->field.le_prev = \t\t\t\\\n\t\t    (elm)->field.le_prev;\t\t\t\t\\\n\t*(elm)->field.le_prev = (elm)->field.le_next;\t\t\t\\\n} while (/*CONSTCOND*/0)\n\n#define\tLIST_FOREACH(var, head, field)\t\t\t\t\t\\\n\tfor ((var) = ((head)->lh_first);\t\t\t\t\\\n\t\t(var);\t\t\t\t\t\t\t\\\n\t\t(var) = ((var)->field.le_next))\n\n/*\n * List access methods.\n */\n#define\tLIST_EMPTY(head)\t\t((head)->lh_first == NULL)\n#define\tLIST_FIRST(head)\t\t((head)->lh_first)\n#define\tLIST_NEXT(elm, field)\t\t((elm)->field.le_next)\n\n\n/*\n * Singly-linked List definitions.\n */\n#define\tSLIST_HEAD(name, type)\t\t\t\t\t\t\\\nstruct name {\t\t\t\t\t\t\t\t\\\n\tstruct type *slh_first;\t/* first element */\t\t\t\\\n}\n\n#define\tSLIST_HEAD_INITIALIZER(head)\t\t\t\t\t\\\n\t{ NULL }\n\n#define\tSLIST_ENTRY(type)\t\t\t\t\t\t\\\nstruct {\t\t\t\t\t\t\t\t\\\n\tstruct type *sle_next;\t/* next element */\t\t\t\\\n}\n\n/*\n * Singly-linked List functions.\n */\n#define\tSLIST_INIT(head) do {\t\t\t\t\t\t\\\n\t(head)->slh_first = NULL;\t\t\t\t\t\\\n} while (/*CONSTCOND*/0)\n\n#define\tSLIST_INSERT_AFTER(slistelm, elm, field) do {\t\t\t\\\n\t(elm)->field.sle_next = (slistelm)->field.sle_next;\t\t\\\n\t(slistelm)->field.sle_next = (elm);\t\t\t\t\\\n} while (/*CONSTCOND*/0)\n\n#define\tSLIST_INSERT_HEAD(head, elm, field) do {\t\t\t\\\n\t(elm)->field.sle_next = (head)->slh_first;\t\t\t\\\n\t(head)->slh_first = (elm);\t\t\t\t\t\\\n} while (/*CONSTCOND*/0)\n\n#define\tSLIST_REMOVE_HEAD(head, field) do {\t\t\t\t\\\n\t(head)->slh_first = (head)->slh_first->field.sle_next;\t\t\\\n} while (/*CONSTCOND*/0)\n\n#define\tSLIST_REMOVE(head, elm, type, field) do {\t\t\t\\\n\tif ((head)->slh_first == (elm)) {\t\t\t\t\\\n\t\tSLIST_REMOVE_HEAD((head), field);\t\t\t\\\n\t}\t\t\t\t\t\t\t\t\\\n\telse {\t\t\t\t\t\t\t\t\\\n\t\tstruct type *curelm = (head)->slh_first;\t\t\\\n\t\twhile(curelm->field.sle_next != (elm))\t\t\t\\\n\t\t\tcurelm = curelm->field.sle_next;\t\t\\\n\t\tcurelm->field.sle_next =\t\t\t\t\\\n\t\t    curelm->field.sle_next->field.sle_next;\t\t\\\n\t}\t\t\t\t\t\t\t\t\\\n} while (/*CONSTCOND*/0)\n\n#define\tSLIST_FOREACH(var, head, field)\t\t\t\t\t\\\n\tfor((var) = (head)->slh_first; (var); (var) = (var)->field.sle_next)\n\n/*\n * Singly-linked List access methods.\n */\n#define\tSLIST_EMPTY(head)\t((head)->slh_first == NULL)\n#define\tSLIST_FIRST(head)\t((head)->slh_first)\n#define\tSLIST_NEXT(elm, field)\t((elm)->field.sle_next)\n\n\n/*\n * Singly-linked Tail queue declarations.\n */\n#define\tSTAILQ_HEAD(name, type)\t\t\t\t\t\\\nstruct name {\t\t\t\t\t\t\t\t\\\n\tstruct type *stqh_first;\t/* first element */\t\t\t\\\n\tstruct type **stqh_last;\t/* addr of last next element */\t\t\\\n}\n\n#define\tSTAILQ_HEAD_INITIALIZER(head)\t\t\t\t\t\\\n\t{ NULL, &(head).stqh_first }\n\n#define\tSTAILQ_ENTRY(type)\t\t\t\t\t\t\\\nstruct {\t\t\t\t\t\t\t\t\\\n\tstruct type *stqe_next;\t/* next element */\t\t\t\\\n}\n\n/*\n * Singly-linked Tail queue functions.\n */\n#define\tSTAILQ_INIT(head) do {\t\t\t\t\t\t\\\n\t(head)->stqh_first = NULL;\t\t\t\t\t\\\n\t(head)->stqh_last = &(head)->stqh_first;\t\t\t\t\\\n} while (/*CONSTCOND*/0)\n\n#define\tSTAILQ_INSERT_HEAD(head, elm, field) do {\t\t\t\\\n\tif (((elm)->field.stqe_next = (head)->stqh_first) == NULL)\t\\\n\t\t(head)->stqh_last = &(elm)->field.stqe_next;\t\t\\\n\t(head)->stqh_first = (elm);\t\t\t\t\t\\\n} while (/*CONSTCOND*/0)\n\n#define\tSTAILQ_INSERT_TAIL(head, elm, field) do {\t\t\t\\\n\t(elm)->field.stqe_next = NULL;\t\t\t\t\t\\\n\t*(head)->stqh_last = (elm);\t\t\t\t\t\\\n\t(head)->stqh_last = &(elm)->field.stqe_next;\t\t\t\\\n} while (/*CONSTCOND*/0)\n\n#define\tSTAILQ_INSERT_AFTER(head, listelm, elm, field) do {\t\t\\\n\tif (((elm)->field.stqe_next = (listelm)->field.stqe_next) == NULL)\\\n\t\t(head)->stqh_last = &(elm)->field.stqe_next;\t\t\\\n\t(listelm)->field.stqe_next = (elm);\t\t\t\t\\\n} while (/*CONSTCOND*/0)\n\n#define\tSTAILQ_REMOVE_HEAD(head, field) do {\t\t\t\t\\\n\tif (((head)->stqh_first = (head)->stqh_first->field.stqe_next) == NULL) \\\n\t\t(head)->stqh_last = &(head)->stqh_first;\t\t\t\\\n} while (/*CONSTCOND*/0)\n\n#define\tSTAILQ_REMOVE(head, elm, type, field) do {\t\t\t\\\n\tif ((head)->stqh_first == (elm)) {\t\t\t\t\\\n\t\tSTAILQ_REMOVE_HEAD((head), field);\t\t\t\\\n\t} else {\t\t\t\t\t\t\t\\\n\t\tstruct type *curelm = (head)->stqh_first;\t\t\\\n\t\twhile (curelm->field.stqe_next != (elm))\t\t\t\\\n\t\t\tcurelm = curelm->field.stqe_next;\t\t\\\n\t\tif ((curelm->field.stqe_next =\t\t\t\t\\\n\t\t\tcurelm->field.stqe_next->field.stqe_next) == NULL) \\\n\t\t\t    (head)->stqh_last = &(curelm)->field.stqe_next; \\\n\t}\t\t\t\t\t\t\t\t\\\n} while (/*CONSTCOND*/0)\n\n#define\tSTAILQ_FOREACH(var, head, field)\t\t\t\t\\\n\tfor ((var) = ((head)->stqh_first);\t\t\t\t\\\n\t\t(var);\t\t\t\t\t\t\t\\\n\t\t(var) = ((var)->field.stqe_next))\n\n/*\n * Singly-linked Tail queue access methods.\n */\n#define\tSTAILQ_EMPTY(head)\t((head)->stqh_first == NULL)\n#define\tSTAILQ_FIRST(head)\t((head)->stqh_first)\n#define\tSTAILQ_NEXT(elm, field)\t((elm)->field.stqe_next)\n\n\n/*\n * Simple queue definitions.\n */\n#define\tSIMPLEQ_HEAD(name, type)\t\t\t\t\t\\\nstruct name {\t\t\t\t\t\t\t\t\\\n\tstruct type *sqh_first;\t/* first element */\t\t\t\\\n\tstruct type **sqh_last;\t/* addr of last next element */\t\t\\\n}\n\n#define\tSIMPLEQ_HEAD_INITIALIZER(head)\t\t\t\t\t\\\n\t{ NULL, &(head).sqh_first }\n\n#define\tSIMPLEQ_ENTRY(type)\t\t\t\t\t\t\\\nstruct {\t\t\t\t\t\t\t\t\\\n\tstruct type *sqe_next;\t/* next element */\t\t\t\\\n}\n\n/*\n * Simple queue functions.\n */\n#define\tSIMPLEQ_INIT(head) do {\t\t\t\t\t\t\\\n\t(head)->sqh_first = NULL;\t\t\t\t\t\\\n\t(head)->sqh_last = &(head)->sqh_first;\t\t\t\t\\\n} while (/*CONSTCOND*/0)\n\n#define\tSIMPLEQ_INSERT_HEAD(head, elm, field) do {\t\t\t\\\n\tif (((elm)->field.sqe_next = (head)->sqh_first) == NULL)\t\\\n\t\t(head)->sqh_last = &(elm)->field.sqe_next;\t\t\\\n\t(head)->sqh_first = (elm);\t\t\t\t\t\\\n} while (/*CONSTCOND*/0)\n\n#define\tSIMPLEQ_INSERT_TAIL(head, elm, field) do {\t\t\t\\\n\t(elm)->field.sqe_next = NULL;\t\t\t\t\t\\\n\t*(head)->sqh_last = (elm);\t\t\t\t\t\\\n\t(head)->sqh_last = &(elm)->field.sqe_next;\t\t\t\\\n} while (/*CONSTCOND*/0)\n\n#define\tSIMPLEQ_INSERT_AFTER(head, listelm, elm, field) do {\t\t\\\n\tif (((elm)->field.sqe_next = (listelm)->field.sqe_next) == NULL)\\\n\t\t(head)->sqh_last = &(elm)->field.sqe_next;\t\t\\\n\t(listelm)->field.sqe_next = (elm);\t\t\t\t\\\n} while (/*CONSTCOND*/0)\n\n#define\tSIMPLEQ_REMOVE_HEAD(head, field) do {\t\t\t\t\\\n\tif (((head)->sqh_first = (head)->sqh_first->field.sqe_next) == NULL) \\\n\t\t(head)->sqh_last = &(head)->sqh_first;\t\t\t\\\n} while (/*CONSTCOND*/0)\n\n#define\tSIMPLEQ_REMOVE(head, elm, type, field) do {\t\t\t\\\n\tif ((head)->sqh_first == (elm)) {\t\t\t\t\\\n\t\tSIMPLEQ_REMOVE_HEAD((head), field);\t\t\t\\\n\t} else {\t\t\t\t\t\t\t\\\n\t\tstruct type *curelm = (head)->sqh_first;\t\t\\\n\t\twhile (curelm->field.sqe_next != (elm))\t\t\t\\\n\t\t\tcurelm = curelm->field.sqe_next;\t\t\\\n\t\tif ((curelm->field.sqe_next =\t\t\t\t\\\n\t\t\tcurelm->field.sqe_next->field.sqe_next) == NULL) \\\n\t\t\t    (head)->sqh_last = &(curelm)->field.sqe_next; \\\n\t}\t\t\t\t\t\t\t\t\\\n} while (/*CONSTCOND*/0)\n\n#define\tSIMPLEQ_FOREACH(var, head, field)\t\t\t\t\\\n\tfor ((var) = ((head)->sqh_first);\t\t\t\t\\\n\t\t(var);\t\t\t\t\t\t\t\\\n\t\t(var) = ((var)->field.sqe_next))\n\n/*\n * Simple queue access methods.\n */\n#define\tSIMPLEQ_EMPTY(head)\t\t((head)->sqh_first == NULL)\n#define\tSIMPLEQ_FIRST(head)\t\t((head)->sqh_first)\n#define\tSIMPLEQ_NEXT(elm, field)\t((elm)->field.sqe_next)\n\n\n/*\n * Tail queue definitions.\n */\n#define\t_TAILQ_HEAD(name, type, qual)\t\t\t\t\t\\\nstruct name {\t\t\t\t\t\t\t\t\\\n\tqual type *tqh_first;\t\t/* first element */\t\t\\\n\tqual type *qual *tqh_last;\t/* addr of last next element */\t\\\n}\n#define TAILQ_HEAD(name, type)\t_TAILQ_HEAD(name, struct type,)\n\n#define\tTAILQ_HEAD_INITIALIZER(head)\t\t\t\t\t\\\n\t{ NULL, &(head).tqh_first }\n\n#define\t_TAILQ_ENTRY(type, qual)\t\t\t\t\t\\\nstruct {\t\t\t\t\t\t\t\t\\\n\tqual type *tqe_next;\t\t/* next element */\t\t\\\n\tqual type *qual *tqe_prev;\t/* address of previous next element */\\\n}\n#define TAILQ_ENTRY(type)\t_TAILQ_ENTRY(struct type,)\n\n/*\n * Tail queue functions.\n */\n#define\tTAILQ_INIT(head) do {\t\t\t\t\t\t\\\n\t(head)->tqh_first = NULL;\t\t\t\t\t\\\n\t(head)->tqh_last = &(head)->tqh_first;\t\t\t\t\\\n} while (/*CONSTCOND*/0)\n\n#define\tTAILQ_INSERT_HEAD(head, elm, field) do {\t\t\t\\\n\tif (((elm)->field.tqe_next = (head)->tqh_first) != NULL)\t\\\n\t\t(head)->tqh_first->field.tqe_prev =\t\t\t\\\n\t\t    &(elm)->field.tqe_next;\t\t\t\t\\\n\telse\t\t\t\t\t\t\t\t\\\n\t\t(head)->tqh_last = &(elm)->field.tqe_next;\t\t\\\n\t(head)->tqh_first = (elm);\t\t\t\t\t\\\n\t(elm)->field.tqe_prev = &(head)->tqh_first;\t\t\t\\\n} while (/*CONSTCOND*/0)\n\n#define\tTAILQ_INSERT_TAIL(head, elm, field) do {\t\t\t\\\n\t(elm)->field.tqe_next = NULL;\t\t\t\t\t\\\n\t(elm)->field.tqe_prev = (head)->tqh_last;\t\t\t\\\n\t*(head)->tqh_last = (elm);\t\t\t\t\t\\\n\t(head)->tqh_last = &(elm)->field.tqe_next;\t\t\t\\\n} while (/*CONSTCOND*/0)\n\n#define\tTAILQ_INSERT_AFTER(head, listelm, elm, field) do {\t\t\\\n\tif (((elm)->field.tqe_next = (listelm)->field.tqe_next) != NULL)\\\n\t\t(elm)->field.tqe_next->field.tqe_prev = \t\t\\\n\t\t    &(elm)->field.tqe_next;\t\t\t\t\\\n\telse\t\t\t\t\t\t\t\t\\\n\t\t(head)->tqh_last = &(elm)->field.tqe_next;\t\t\\\n\t(listelm)->field.tqe_next = (elm);\t\t\t\t\\\n\t(elm)->field.tqe_prev = &(listelm)->field.tqe_next;\t\t\\\n} while (/*CONSTCOND*/0)\n\n#define\tTAILQ_INSERT_BEFORE(listelm, elm, field) do {\t\t\t\\\n\t(elm)->field.tqe_prev = (listelm)->field.tqe_prev;\t\t\\\n\t(elm)->field.tqe_next = (listelm);\t\t\t\t\\\n\t*(listelm)->field.tqe_prev = (elm);\t\t\t\t\\\n\t(listelm)->field.tqe_prev = &(elm)->field.tqe_next;\t\t\\\n} while (/*CONSTCOND*/0)\n\n#define\tTAILQ_REMOVE(head, elm, field) do {\t\t\t\t\\\n\tif (((elm)->field.tqe_next) != NULL)\t\t\t\t\\\n\t\t(elm)->field.tqe_next->field.tqe_prev = \t\t\\\n\t\t    (elm)->field.tqe_prev;\t\t\t\t\\\n\telse\t\t\t\t\t\t\t\t\\\n\t\t(head)->tqh_last = (elm)->field.tqe_prev;\t\t\\\n\t*(elm)->field.tqe_prev = (elm)->field.tqe_next;\t\t\t\\\n} while (/*CONSTCOND*/0)\n\n#define\tTAILQ_FOREACH(var, head, field)\t\t\t\t\t\\\n\tfor ((var) = ((head)->tqh_first);\t\t\t\t\\\n\t\t(var);\t\t\t\t\t\t\t\\\n\t\t(var) = ((var)->field.tqe_next))\n\n#define\tTAILQ_FOREACH_REVERSE(var, head, headname, field)\t\t\\\n\tfor ((var) = (*(((struct headname *)((head)->tqh_last))->tqh_last));\t\\\n\t\t(var);\t\t\t\t\t\t\t\\\n\t\t(var) = (*(((struct headname *)((var)->field.tqe_prev))->tqh_last)))\n\n/*\n * Tail queue access methods.\n */\n#define\tTAILQ_EMPTY(head)\t\t((head)->tqh_first == NULL)\n#define\tTAILQ_FIRST(head)\t\t((head)->tqh_first)\n#define\tTAILQ_NEXT(elm, field)\t\t((elm)->field.tqe_next)\n\n#define\tTAILQ_LAST(head, headname) \\\n\t(*(((struct headname *)((head)->tqh_last))->tqh_last))\n#define\tTAILQ_PREV(elm, headname, field) \\\n\t(*(((struct headname *)((elm)->field.tqe_prev))->tqh_last))\n\n\n/*\n * Circular queue definitions.\n */\n#define\tCIRCLEQ_HEAD(name, type)\t\t\t\t\t\\\nstruct name {\t\t\t\t\t\t\t\t\\\n\tstruct type *cqh_first;\t\t/* first element */\t\t\\\n\tstruct type *cqh_last;\t\t/* last element */\t\t\\\n}\n\n#define\tCIRCLEQ_HEAD_INITIALIZER(head)\t\t\t\t\t\\\n\t{ (void *)&head, (void *)&head }\n\n#define\tCIRCLEQ_ENTRY(type)\t\t\t\t\t\t\\\nstruct {\t\t\t\t\t\t\t\t\\\n\tstruct type *cqe_next;\t\t/* next element */\t\t\\\n\tstruct type *cqe_prev;\t\t/* previous element */\t\t\\\n}\n\n/*\n * Circular queue functions.\n */\n#define\tCIRCLEQ_INIT(head) do {\t\t\t\t\t\t\\\n\t(head)->cqh_first = (void *)(head);\t\t\t\t\\\n\t(head)->cqh_last = (void *)(head);\t\t\t\t\\\n} while (/*CONSTCOND*/0)\n\n#define\tCIRCLEQ_INSERT_AFTER(head, listelm, elm, field) do {\t\t\\\n\t(elm)->field.cqe_next = (listelm)->field.cqe_next;\t\t\\\n\t(elm)->field.cqe_prev = (listelm);\t\t\t\t\\\n\tif ((listelm)->field.cqe_next == (void *)(head))\t\t\\\n\t\t(head)->cqh_last = (elm);\t\t\t\t\\\n\telse\t\t\t\t\t\t\t\t\\\n\t\t(listelm)->field.cqe_next->field.cqe_prev = (elm);\t\\\n\t(listelm)->field.cqe_next = (elm);\t\t\t\t\\\n} while (/*CONSTCOND*/0)\n\n#define\tCIRCLEQ_INSERT_BEFORE(head, listelm, elm, field) do {\t\t\\\n\t(elm)->field.cqe_next = (listelm);\t\t\t\t\\\n\t(elm)->field.cqe_prev = (listelm)->field.cqe_prev;\t\t\\\n\tif ((listelm)->field.cqe_prev == (void *)(head))\t\t\\\n\t\t(head)->cqh_first = (elm);\t\t\t\t\\\n\telse\t\t\t\t\t\t\t\t\\\n\t\t(listelm)->field.cqe_prev->field.cqe_next = (elm);\t\\\n\t(listelm)->field.cqe_prev = (elm);\t\t\t\t\\\n} while (/*CONSTCOND*/0)\n\n#define\tCIRCLEQ_INSERT_HEAD(head, elm, field) do {\t\t\t\\\n\t(elm)->field.cqe_next = (head)->cqh_first;\t\t\t\\\n\t(elm)->field.cqe_prev = (void *)(head);\t\t\t\t\\\n\tif ((head)->cqh_last == (void *)(head))\t\t\t\t\\\n\t\t(head)->cqh_last = (elm);\t\t\t\t\\\n\telse\t\t\t\t\t\t\t\t\\\n\t\t(head)->cqh_first->field.cqe_prev = (elm);\t\t\\\n\t(head)->cqh_first = (elm);\t\t\t\t\t\\\n} while (/*CONSTCOND*/0)\n\n#define\tCIRCLEQ_INSERT_TAIL(head, elm, field) do {\t\t\t\\\n\t(elm)->field.cqe_next = (void *)(head);\t\t\t\t\\\n\t(elm)->field.cqe_prev = (head)->cqh_last;\t\t\t\\\n\tif ((head)->cqh_first == (void *)(head))\t\t\t\\\n\t\t(head)->cqh_first = (elm);\t\t\t\t\\\n\telse\t\t\t\t\t\t\t\t\\\n\t\t(head)->cqh_last->field.cqe_next = (elm);\t\t\\\n\t(head)->cqh_last = (elm);\t\t\t\t\t\\\n} while (/*CONSTCOND*/0)\n\n#define\tCIRCLEQ_REMOVE(head, elm, field) do {\t\t\t\t\\\n\tif ((elm)->field.cqe_next == (void *)(head))\t\t\t\\\n\t\t(head)->cqh_last = (elm)->field.cqe_prev;\t\t\\\n\telse\t\t\t\t\t\t\t\t\\\n\t\t(elm)->field.cqe_next->field.cqe_prev =\t\t\t\\\n\t\t    (elm)->field.cqe_prev;\t\t\t\t\\\n\tif ((elm)->field.cqe_prev == (void *)(head))\t\t\t\\\n\t\t(head)->cqh_first = (elm)->field.cqe_next;\t\t\\\n\telse\t\t\t\t\t\t\t\t\\\n\t\t(elm)->field.cqe_prev->field.cqe_next =\t\t\t\\\n\t\t    (elm)->field.cqe_next;\t\t\t\t\\\n} while (/*CONSTCOND*/0)\n\n#define\tCIRCLEQ_FOREACH(var, head, field)\t\t\t\t\\\n\tfor ((var) = ((head)->cqh_first);\t\t\t\t\\\n\t\t(var) != (const void *)(head);\t\t\t\t\\\n\t\t(var) = ((var)->field.cqe_next))\n\n#define\tCIRCLEQ_FOREACH_REVERSE(var, head, field)\t\t\t\\\n\tfor ((var) = ((head)->cqh_last);\t\t\t\t\\\n\t\t(var) != (const void *)(head);\t\t\t\t\\\n\t\t(var) = ((var)->field.cqe_prev))\n\n/*\n * Circular queue access methods.\n */\n#define\tCIRCLEQ_EMPTY(head)\t\t((head)->cqh_first == (void *)(head))\n#define\tCIRCLEQ_FIRST(head)\t\t((head)->cqh_first)\n#define\tCIRCLEQ_LAST(head)\t\t((head)->cqh_last)\n#define\tCIRCLEQ_NEXT(elm, field)\t((elm)->field.cqe_next)\n#define\tCIRCLEQ_PREV(elm, field)\t((elm)->field.cqe_prev)\n\n#define CIRCLEQ_LOOP_NEXT(head, elm, field)\t\t\t\t\\\n\t(((elm)->field.cqe_next == (void *)(head))\t\t\t\\\n\t    ? ((head)->cqh_first)\t\t\t\t\t\\\n\t    : (elm->field.cqe_next))\n#define CIRCLEQ_LOOP_PREV(head, elm, field)\t\t\t\t\\\n\t(((elm)->field.cqe_prev == (void *)(head))\t\t\t\\\n\t    ? ((head)->cqh_last)\t\t\t\t\t\\\n\t    : (elm->field.cqe_prev))\n\n#endif\t/* sys/queue.h */\n"
  },
  {
    "path": "libspotify/examples/localfiles/Makefile",
    "content": "TARGET=posix_stu\nCFLAGs += -Werror\n\ninclude ../common.mk\n\n$(TARGET): main.o appkey.o\n\t$(CC) $(CFLAGS) $(LDFLAGS) $^ -o $@ $(LDLIBS)\n\nifdef DEBUG\nifeq ($(shell uname),Darwin)\n\tinstall_name_tool -change @loader_path/../Frameworks/libspotify.framework/libspotify @rpath/libspotify.so $@\nendif\nendif\n"
  },
  {
    "path": "libspotify/examples/localfiles/main.c",
    "content": "/**\n * Copyright (c) 2006-2010 Spotify Ltd\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n *\n */\n\n#define USER_AGENT \"testlocal\"\n/* A simple stub that logs in and out */\n\n#include \"main.h\"\n#include <pthread.h>\n#include <stdlib.h>\n#include <stdio.h>\n#include <unistd.h>\n#include <sys/time.h>\nsp_session *g_session;\n\nstatic int notify_events;\nstatic pthread_mutex_t notify_mutex;\nstatic pthread_cond_t notify_cond;\n\n\nstatic void connection_error(sp_session *session, sp_error error)\n{\n\t\n}\n\nstatic void logged_in(sp_session *session, sp_error error)\n{\n\t//add your testcode here\n        if (error != SP_ERROR_OK) {\n\t\tfprintf(stderr, \"failed to login: %s\\n\",\n\t\t                sp_error_message(error));\n                exit(1);\n        }\n\n\tsp_track *track = sp_localtrack_create(\"Turboweekend\",\"Something Or Nothing - Acid Washed Remix\",\"\",-1);\n\tsp_playlistcontainer *pc = sp_session_playlistcontainer(session);\n\tsp_playlist *pl = sp_playlistcontainer_add_new_playlist(pc,\"localtest\");\n\tsp_playlist_add_tracks(pl,&track,1,0,session);\n\t//sp_session_logout(session);\n}\n\nstatic void logged_out(sp_session *session)\n{\n\texit(0);\n}\n\n\n/**\n * This callback is called for log messages.\n *\n * @sa sp_session_callbacks#log_message\n */\nstatic void log_message(sp_session *session, const char *data)\n{\n\tfprintf(stderr,\"%s\",data);\n}\n\nvoid notify_main_thread(sp_session *session)\n{\n\tpthread_mutex_lock(&notify_mutex);\n\tnotify_events = 1;\n\tpthread_cond_signal(&notify_cond);\n\tpthread_mutex_unlock(&notify_mutex);\n}\n\nstatic sp_session_callbacks callbacks = {\n\t&logged_in,\n\t&logged_out,\n\tNULL,\n\t&connection_error,\n\tNULL,\n\t&notify_main_thread,\n\tNULL,\n\tNULL,\n\t&log_message\n};\n\nint spotify_init(const char *username,const char *password)\n{\n\tsp_session_config config;\n\tsp_error error;\n\tsp_session *session;\n\t\n\t/// The application key is specific to each project, and allows Spotify\n\t/// to produce statistics on how our service is used.\n\textern const char g_appkey[];\n\t/// The size of the application key.\n\textern const size_t g_appkey_size;\n\n\t// Always do this. It allows libspotify to check for\n\t// header/library inconsistencies.\n\tconfig.api_version = SPOTIFY_API_VERSION;\n\n\t// The path of the directory to store the cache. This must be specified.\n\t// Please read the documentation on preferred values.\n\tconfig.cache_location = \"tmp\";\n\n\t// The path of the directory to store the settings. \n\t// This must be specified.\n\t// Please read the documentation on preferred values.\n\tconfig.settings_location = \"tmp\";\n\n\t// The key of the application. They are generated by Spotify,\n\t// and are specific to each application using libspotify.\n\tconfig.application_key = g_appkey;\n\tconfig.application_key_size = g_appkey_size;\n\n\t// This identifies the application using some\n\t// free-text string [1, 255] characters.\n\tconfig.user_agent = USER_AGENT;\n\n\t// Register the callbacks.\n\tconfig.callbacks = &callbacks;\n\n\terror = sp_session_create(&config, &session);\n\tif (SP_ERROR_OK != error) {\n\t\tfprintf(stderr, \"failed to create session: %s\\n\",\n\t\t                sp_error_message(error));\n\t\treturn 2;\n\t}\n\n\t// Login using the credentials given on the command line.\n\tsp_session_login(session, username, password, 0, NULL);\n\n\tif (SP_ERROR_OK != error) {\n\t\tfprintf(stderr, \"failed to login: %s\\n\",\n\t\t                sp_error_message(error));\n\t\treturn 3;\n\t}\n\n\tg_session = session;\n\treturn 0;\n}\n\nint main(int argc, char **argv)\n{\n\tint next_timeout = 0;\n\tif(argc < 3) {\n\t\tfprintf(stderr,\"Usage: %s <username> <password>\\n\",argv[0]);\n\t\treturn -1;\n\t}\n\tpthread_mutex_init(&notify_mutex, NULL);\n\tpthread_cond_init(&notify_cond, NULL);\n\n\tif(spotify_init(argv[1],argv[2]) != 0) {\n\t\tfprintf(stderr,\"Spotify failed to initialize\\n\");\n\t\texit(-1);\n\t}\n\tpthread_mutex_lock(&notify_mutex);\n\tfor (;;) {\n\t\tif (next_timeout == 0) {\n\t\t\twhile(!notify_events)\n\t\t\t\tpthread_cond_wait(&notify_cond, &notify_mutex);\n\t\t} else {\n\t\t\tstruct timespec ts;\n\n\t#if _POSIX_TIMERS > 0\n\t\t\tclock_gettime(CLOCK_REALTIME, &ts);\n\t#else\n\t\t\tstruct timeval tv;\n\t\t\tgettimeofday(&tv, NULL);\n\t\t\tTIMEVAL_TO_TIMESPEC(&tv, &ts);\n\t#endif\n\n\t\t\tts.tv_sec += next_timeout / 1000;\n\t\t\tts.tv_nsec += (next_timeout % 1000) * 1000000;\n\n\t\t\twhile(!notify_events) {\n\t\t\t\tif(pthread_cond_timedwait(&notify_cond, &notify_mutex, &ts))\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\t// Process libspotify events\n\t\tnotify_events = 0;\n\t\tpthread_mutex_unlock(&notify_mutex);\n\n\t\tdo {\n\t\t\tsp_session_process_events(g_session, &next_timeout);\n\t\t} while (next_timeout == 0);\n\n\t\tpthread_mutex_lock(&notify_mutex);\n\t}\n\treturn 0;\n}\n"
  },
  {
    "path": "libspotify/examples/localfiles/main.h",
    "content": "#ifndef __MAIN_H__\n#define __MAIN_H__\n#include <libspotify/api.h>\n#endif\n"
  },
  {
    "path": "libspotify/examples/spshell/Makefile",
    "content": "TARGET=spshell\nLDLIBS += -lreadline\n\n\nifdef SP_LIBSPOTIFY_WITH_SCROBBLING\nCFLAGS += -DSP_LIBSPOTIFY_WITH_SCROBBLING=1\nOBJS += scrobbling.o\nendif\n\ninclude ../common.mk\n\nOBJS += spshell.o spshell_posix.o appkey.o cmd.o browse.o search.o toplist.o inbox.o star.o playlist.o test.o\n\n\n\n$(TARGET): $(OBJS)\n\t$(CC) $(CFLAGS) $(LDFLAGS) $^ $(LDLIBS) -o $@\nifdef DEBUG\nifeq ($(shell uname),Darwin)\n\tinstall_name_tool -change @loader_path/../Frameworks/libspotify.framework/libspotify @rpath/libspotify.so $@\nendif\nendif\n"
  },
  {
    "path": "libspotify/examples/spshell/browse.c",
    "content": "/**\n * Copyright (c) 2006-2010 Spotify Ltd\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n *\n */\n\n#include \"spshell.h\"\n#include \"cmd.h\"\n\nstatic sp_track *track_browse;\nstatic sp_playlist *playlist_browse;\nstatic sp_playlist_callbacks pl_callbacks;\n\n/**\n * Print the given track title together with some trivial metadata\n *\n * @param  track   The track object\n */\nvoid print_track(sp_track *track)\n{\n\tint duration = sp_track_duration(track);\n\tchar url[256];\n\tsp_link *l;\n\tint i;\n\n#if WIN32\n\tprintf(\" %s \", sp_track_is_starred(g_session,track) ? \"*\" : \" \");\n#else\n\tprintf(\" %s \", sp_track_is_starred(g_session,track) ? \"★\" : \"☆\");\n#endif\n\tprintf(\"Track %s [%d:%02d] has %d artist(s), %d%% popularity\",\n\t       sp_track_name(track),\n\t       duration / 60000,\n\t       (duration / 1000) % 60,\n\t       sp_track_num_artists(track),\n\t       sp_track_popularity(track));\n\t\n\tif(sp_track_disc(track)) \n\t\tprintf(\", %d on disc %d\",\n\t\t       sp_track_index(track),\n\t\t       sp_track_disc(track));\n\tprintf(\"\\n\");\n\n\tfor (i = 0; i < sp_track_num_artists(track); i++) {\n\t\tsp_artist *art = sp_track_artist(track, i);\n\t\tprintf(\"\\tArtist %d: %s\\n\", i + 1, sp_artist_name(art));\n\t}\n\tl = sp_link_create_from_track(track, 0);\n\tsp_link_as_string(l, url, sizeof(url));\n\tprintf(\"\\t\\t%s\\n\", url);\n\tsp_link_release(l);\n}\n\n/**\n * Print the given album browse result and as much information as possible\n *\n * @param  browse  The browse result\n */\nstatic void print_albumbrowse(sp_albumbrowse *browse)\n{\n\tint i;\n\n\tprintf(\"Album browse of \\\"%s\\\" (%d)\\n\", \n\t       sp_album_name(sp_albumbrowse_album(browse)), \n\t       sp_album_year(sp_albumbrowse_album(browse)));\n\n\tfor (i = 0; i < sp_albumbrowse_num_copyrights(browse); ++i)\n\t\tprintf(\"  Copyright: %s\\n\", sp_albumbrowse_copyright(browse, i));\n\n\tprintf(\"  Tracks: %d\\n\", sp_albumbrowse_num_tracks(browse));\n\tprintf(\"  Review: %.60s...\\n\", sp_albumbrowse_review(browse));\n\tputs(\"\");\n\n\tfor (i = 0; i < sp_albumbrowse_num_tracks(browse); ++i)\n\t\tprint_track(sp_albumbrowse_track(browse, i));\n\n\tputs(\"\");\n}\n\n/**\n * Print the given artist browse result and as much information as possible\n *\n * @param  browse  The browse result\n */\nstatic void print_artistbrowse(sp_artistbrowse *browse)\n{\n\tint i;\n\n\tprintf(\"Artist browse of \\\"%s\\\"\\n\", sp_artist_name(sp_artistbrowse_artist(browse)));\n\n\tfor (i = 0; i < sp_artistbrowse_num_similar_artists(browse); ++i)\n\t\tprintf(\"  Similar artist: %s\\n\", sp_artist_name(sp_artistbrowse_similar_artist(browse, i)));\n\n\tprintf(\"  Portraits: %d\\n\", sp_artistbrowse_num_portraits(browse));\n\tprintf(\"  Tracks   : %d\\n\", sp_artistbrowse_num_tracks(browse));\n\tprintf(\"  Biography: %.60s...\\n\", sp_artistbrowse_biography(browse));\n\tputs(\"\");\n\n\tfor (i = 0; i < sp_artistbrowse_num_tracks(browse); ++i)\n\t\tprint_track(sp_artistbrowse_track(browse, i));\n\n\tputs(\"\");\n}\n\n\n\n/**\n * Callback for libspotify\n *\n * @param browse    The browse result object that is now done\n * @param userdata  The opaque pointer given to sp_albumbrowse_create()\n */\nstatic void SP_CALLCONV browse_album_callback(sp_albumbrowse *browse, void *userdata)\n{\n\tif (sp_albumbrowse_error(browse) == SP_ERROR_OK)\n\t\tprint_albumbrowse(browse);\n\telse\n\t\tfprintf(stderr, \"Failed to browse album: %s\\n\",\n\t\t        sp_error_message(sp_albumbrowse_error(browse)));\n\n\tsp_albumbrowse_release(browse);\n\tcmd_done();\n}\n\n\n/**\n * Callback for libspotify\n *\n * @param browse    The browse result object that is now done\n * @param userdata  The opaque pointer given to sp_artistbrowse_create()\n */\nstatic void SP_CALLCONV browse_artist_callback(sp_artistbrowse *browse, void *userdata)\n{\n\tif (sp_artistbrowse_error(browse) == SP_ERROR_OK)\n\t\tprint_artistbrowse(browse);\n\telse\n\t\tfprintf(stderr, \"Failed to browse artist: %s\\n\",\n\t\t        sp_error_message(sp_artistbrowse_error(browse)));\n\n\tsp_artistbrowse_release(browse);\n\tcmd_done();\n}\n\n\n\n/**\n *\n */\nstatic void track_browse_try(void)\n{\n\tswitch (sp_track_error(track_browse)) {\n\tcase SP_ERROR_OK:\n\t\tprint_track(track_browse);\n\t\tbreak;\n\n\tcase SP_ERROR_IS_LOADING:\n\t\treturn; // Still pending\n\n\tdefault:\n\t\tfprintf(stderr, \"Unable to resolve track: %s\\n\", sp_error_message(sp_track_error(track_browse)));\n\t\tbreak;\n\t}\n\t\n\tmetadata_updated_fn = NULL;\n\tcmd_done();\n\tsp_track_release(track_browse);\n}\n\n\n\n/**\n *\n */\nstatic void playlist_browse_try(void)\n{\n\tint i, tracks;\n\n\tmetadata_updated_fn = playlist_browse_try;\n\tif(!sp_playlist_is_loaded(playlist_browse)) {\n\t\tprintf(\"\\tPlaylist not loaded\\n\");\n\t\treturn;\n\t}\n\n\ttracks = sp_playlist_num_tracks(playlist_browse);\n\tfor(i = 0; i < tracks; i++) {\n\t\tsp_track *t = sp_playlist_track(playlist_browse, i);\n\t\tif (!sp_track_is_loaded(t))\n\t\t\treturn;\n\t}\n\n\tprintf(\"\\tPlaylist and metadata loaded\\n\");\n\n\tfor(i = 0; i < tracks; i++) {\n\t\tsp_track *t = sp_playlist_track(playlist_browse, i);\n\t\t\n\t\tprintf(\" %5d: \", i + 1);\n\t\tprint_track(t);\n\t}\n\tsp_playlist_remove_callbacks(playlist_browse, &pl_callbacks, NULL);\n\n\tsp_playlist_release(playlist_browse);\n\tplaylist_browse = NULL;\n\tmetadata_updated_fn = NULL;\n\tcmd_done();\n}\n\n/**\n *\n */\nstatic void SP_CALLCONV pl_tracks_added(sp_playlist *pl, sp_track * const * tracks,\n\t\t\t    int num_tracks, int position, void *userdata)\n{\n\tprintf(\"\\t%d tracks added\\n\", num_tracks);\n}\n\n/**\n *\n */\nstatic void SP_CALLCONV pl_tracks_removed(sp_playlist *pl, const int *tracks,\n\t\t\t      int num_tracks, void *userdata)\n{\n\tprintf(\"\\t%d tracks removed\\n\", num_tracks);\n}\n\n/**\n *\n */\nstatic void SP_CALLCONV pl_tracks_moved(sp_playlist *pl, const int *tracks,\n\t\t\t    int num_tracks, int new_position, void *userdata)\n{\n\tprintf(\"\\t%d tracks moved\\n\", num_tracks);\n}\n\n/**\n *\n */\nstatic void SP_CALLCONV pl_renamed(sp_playlist *pl, void *userdata)\n{\n\tprintf(\"\\tList name: %s\\n\",  sp_playlist_name(pl));\n}\n\n/**\n *\n */\nstatic void SP_CALLCONV pl_state_change(sp_playlist *pl, void *userdata)\n{\n\tplaylist_browse_try();\n}\n\nstatic sp_playlist_callbacks pl_callbacks = {\n\tpl_tracks_added,\n\tpl_tracks_removed,\n\tpl_tracks_moved,\n\tpl_renamed,\n\tpl_state_change,\n};\n\n\nvoid browse_playlist(sp_playlist *pl)\n{\n\tplaylist_browse = pl;\n\tsp_playlist_add_callbacks(playlist_browse, &pl_callbacks, NULL);\n\tplaylist_browse_try();\n}\n\n/**\n *\n */\nstatic void browse_usage(void)\n{\n\tfprintf(stderr, \"Usage: browse <spotify-uri>\\n\");\n}\n\n\n/**\n *\n */\nint cmd_browse(int argc, char **argv)\n{\n\tsp_link *link;\n\n\tif (argc != 2) {\n\t\tbrowse_usage();\n\t\treturn -1;\n\t}\n\n\t\n\tlink = sp_link_create_from_string(argv[1]);\n\t\n\tif (!link) {\n\t\tfprintf(stderr, \"Not a spotify link\\n\");\n\t\treturn -1;\n\t}\n\n\tswitch(sp_link_type(link)) {\n\tdefault:\n\t\tfprintf(stderr, \"Can not handle link\");\n\t\tsp_link_release(link);\n\t\treturn -1;\n\n\tcase SP_LINKTYPE_ALBUM:\n\t\tsp_albumbrowse_create(g_session, sp_link_as_album(link), browse_album_callback, NULL);\n\t\tbreak;\n\n\tcase SP_LINKTYPE_ARTIST:\n\t\tsp_artistbrowse_create(g_session, sp_link_as_artist(link), SP_ARTISTBROWSE_FULL, browse_artist_callback, NULL);\n\t\tbreak;\n\n\tcase SP_LINKTYPE_LOCALTRACK:\n\tcase SP_LINKTYPE_TRACK:\n\t\ttrack_browse = sp_link_as_track(link);\n\t\tmetadata_updated_fn = track_browse_try;\n\t\tsp_track_add_ref(track_browse);\n\t\ttrack_browse_try();\n\t\tbreak;\n\n\tcase SP_LINKTYPE_PLAYLIST:\n\t\tbrowse_playlist(sp_playlist_create(g_session, link));\n\t\tbreak;\n\t}\n\n\tsp_link_release(link);\n\treturn 0;\n}\n"
  },
  {
    "path": "libspotify/examples/spshell/cmd.c",
    "content": "/**\n * Copyright (c) 2006-2010 Spotify Ltd\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n *\n */\n\n#include <string.h>\n\n#include \"spshell.h\"\n#include \"cmd.h\"\n\nstatic int cmd_help(int argc, char **argv);\n\n/**\n *\n */\nstruct {\n\tconst char *name;\n\tint (*fn)(int argc, char **argv);\n\tconst char *help;\n} commands[] = {\n\t{ \"log\",        cmd_log,        \"Enable/Disable logging to console (default off)\" },\n\t{ \"logout\",     cmd_logout,     \"Logout and exit app\" },\n\t{ \"exit\",       cmd_logout,     \"Logout and exit app\" },\n\t{ \"quit\",       cmd_logout,     \"Logout and exit app\" },\n\t{ \"browse\",     cmd_browse,     \"Browse a Spotify URI\" },\n\t{ \"search\",     cmd_search,     \"Search\" },\n\t{ \"whatsnew\",   cmd_whatsnew,   \"List new albums\" },\n\t{ \"toplist\",    cmd_toplist,    \"Browse toplists\" },\n\t{ \"post\",       cmd_post,       \"Post track to a user's inbox\" },\n\t{ \"inbox\",      cmd_inbox,      \"View inbox\" },\n\t{ \"help\",       cmd_help,       \"This help\" },\n\t{ \"star\",       cmd_star,       \"Star a track\" },\n\t{ \"unstar\",     cmd_unstar,     \"Unstar a track\" },\n\t{ \"starred\",    cmd_starred,    \"List all starred tracks\" },\n#if SP_LIBSPOTIFY_WITH_SCROBBLING\n\t{ \"facebook_scrobbling\", cmd_facebook_scrobbling,  \"Enable/Disable facebook scrobbling\" },\n\t{ \"is_facebook_scrobbling\", cmd_is_facebook_scrobbling,  \"Returns facebook scrobbling status\" },\n\t{ \"spotify_social\", cmd_spotify_social,  \"Enable/Disable posting to Spotify Social\" },\n\t{ \"is_spotify_social\", cmd_is_spotify_social,  \"Returns Spotify Social status\" },\n\t{ \"lastfm_scrobbling_credentials\", cmd_set_lastfm_scrobbling_credentials, \"Sets the lastfm scrobbling credentials\" },\n\t{ \"lastfm_scrobbling\", cmd_lastfm_scrobbling, \"Enable/Disable lastfm scrobbling\" },\n\t{ \"is_lastfm_scrobbling\", cmd_is_lastfm_scrobbling, \"Returns lastfm scrobbling status\"},\n\t{ \"private_session\", cmd_private_session, \"Enable/Disable private session\" },\n\t{ \"is_private_session\", cmd_is_private_session, \"Returns private session mode\"},\n#endif\n\t{ \"playlists\",  cmd_playlists,  \"List playlists\" },\n\t{ \"playlist\",   cmd_playlist,   \"List playlist contents\" },\n\t{ \"set_autolink\", cmd_set_autolink, \"Set autolinking state\" },\n\t{ \"add_folder\", cmd_add_folder, \"Add playlist folder\"},\n\t{ \"update_subscriptions\", cmd_update_subscriptions, \"Update playlist subscription info\"},\n\t{ \"add\", cmd_playlist_add_track, \"Add track to playlist\"},\n\t{ \"offline\", cmd_playlist_offline, \"Set offline mode for a playlist\"},\n#if WITH_TEST_COMMAND\n\t{ \"test\", cmd_test, \"Run tests\"},\n#endif\n};\n\n\n/**\n *\n */\nstatic int tokenize(char *buf, char **vec, int vsize)\n{\n\tint n = 0;\n\twhile(1) {\n\t\twhile(*buf > 0 && *buf < 33)\n\t\t\tbuf++;\n\t\tif(!*buf)\n\t\t\tbreak;\n\t\tvec[n++] = buf;\n\t\tif(n == vsize)\n\t\t\tbreak;\n\t\twhile(*buf > 32)\n\t\t\tbuf++;\n\t\tif(*buf == 0)\n\t\t\tbreak;\n\t\t*buf = 0;\n\t\tbuf++;\n\t}\n\treturn n;\n}\n\n\n/**\n *\n */\nvoid cmd_exec_unparsed(char *l)\n{\n\tchar *vec[32];\n\tint c = tokenize(l, vec, 32);\n\tcmd_dispatch(c, vec);\n}\n\n\n/**\n *\n */\nvoid cmd_dispatch(int argc, char **argv)\n{\n\tint i;\n\n\tif(argc < 1) {\n\t\tcmd_done();\n\t\treturn;\n\t}\n\n\tfor(i = 0; i < sizeof(commands) / sizeof(commands[0]); i++) {\n\t\tif(!strcmp(commands[i].name, argv[0])) {\n\t\t\tif(commands[i].fn(argc, argv))\n\t\t\t\tcmd_done();\n\t\t\treturn;\n\t\t}\n\t}\n\tprintf(\"No such command\\n\");\n\tcmd_done();\n}\n\n/**\n *\n */\nstatic int cmd_help(int argc, char **argv)\n{\n\tint i;\n\tfor(i = 0; i < sizeof(commands) / sizeof(commands[0]); i++)\n\t\tprintf(\"  %-20s %s\\n\", commands[i].name, commands[i].help);\n\treturn -1;\n}\n"
  },
  {
    "path": "libspotify/examples/spshell/cmd.h",
    "content": "/**\n * Copyright (c) 2006-2010 Spotify Ltd\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n *\n */\n\n#ifndef CMD_H__\n#define CMD_H__\n\nextern void cmd_exec_unparsed(char *l);\n\nextern void cmd_dispatch(int argc, char **argv);\n\nextern void cmd_done(void);\n\n\nextern int cmd_log(int argc, char **argv);\nextern int cmd_logout(int argc, char **argv);\nextern int cmd_browse(int argc, char **argv);\nextern int cmd_search(int argc, char **argv);\nextern int cmd_whatsnew(int argc, char **argv);\nextern int cmd_toplist(int argc, char **argv);\nextern int cmd_post(int argc, char **argv);\nextern int cmd_star(int argc, char **argv);\nextern int cmd_unstar(int argc, char **argv);\nextern int cmd_starred(int argc, char **argv);\nextern int cmd_inbox(int argc, char **argv);\nextern int cmd_friends(int argc, char **argv);\nextern int cmd_facebook_scrobbling(int argc, char **argv);\nextern int cmd_is_facebook_scrobbling(int argc, char **argv);\nextern int cmd_spotify_social(int argc, char **argv);\nextern int cmd_is_spotify_social(int argc, char **argv);\nextern int cmd_set_lastfm_scrobbling_credentials(int argc, char** argv);\nextern int cmd_lastfm_scrobbling(int argc, char** argv);\nextern int cmd_is_lastfm_scrobbling(int argc, char** argv);\nextern int cmd_private_session(int argc, char** argv);\nextern int cmd_is_private_session(int argc, char** argv);\n\nextern int cmd_playlists(int argc, char **argv);\nextern int cmd_playlist(int argc, char **argv);\nextern int cmd_set_autolink(int argc, char **argv);\n\nextern int cmd_published_playlists(int argc, char **argv);\nextern int cmd_get_published_playlist (int argc, char **argv);\n\nextern int cmd_social_enable(int argc, char **argv);\nextern int cmd_playlists_enable(int argc, char **argv);\nextern int cmd_add_folder(int argc, char **argv);\nextern int cmd_update_subscriptions(int argc, char **argv);\nextern int cmd_playlist_add_track(int argc, char **argv);\nextern int cmd_playlist_offline(int argc, char **argv);\n\n#if WITH_TEST_COMMAND\nextern int cmd_test(int argc, char **argv);\n#endif\n\n/* Shared functions */\nvoid browse_playlist(sp_playlist *pl);\nvoid print_track(sp_track *track);\n\n#endif // CMD_H__\n"
  },
  {
    "path": "libspotify/examples/spshell/inbox.c",
    "content": "/**\n * Copyright (c) 2006-2010 Spotify Ltd\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n *\n */\n\n#include <string.h>\n\n#include \"spshell.h\"\n#include \"cmd.h\"\n\n/**\n *\n */\nstatic void post_usage(void)\n{\n\tfprintf(stderr, \"Usage: post <recipient> <message> [<track-uri> ...]\\n\");\n}\n\n\n/**\n * Callback for libspotify\n *\n * @param result    The inbox result object that is now done\n * @param userdata  The opaque pointer given to sp_inbox_post_tracks()\n */\nstatic void SP_CALLCONV inbox_post_completed(sp_inbox *result, void *userdata)\n{\n\tfprintf(stderr, \"Inbox post result: %s\\n\", sp_error_message(sp_inbox_error(result)));\n\tcmd_done();\n\n}\n\n/**\n *\n */\nint cmd_post(int argc, char **argv)\n{\n\tint num_tracks, i;\n\tsp_track **tracks;\n\tsp_link *link;\n\tsp_inbox *req;\n\n\tif (argc < 3) {\n\t\tpost_usage();\n\t\treturn -1;\n\t}\n\n\tif (argc == 3) {\n\t\t// No arguments, rickroll recipient\n\t\ttracks = malloc(sizeof(sp_track *));\n\t\tlink = sp_link_create_from_string(\"spotify:track:6JEK0CvvjDjjMUBFoXShNZ\");\n\t\tsp_track_add_ref(tracks[0] = sp_link_as_track(link));\n\t\tsp_link_release(link);\n\t\tnum_tracks = 1;\n\t} else {\n\t\ttracks = malloc(sizeof(sp_track *) * (argc - 3));\n\t\tnum_tracks = 0;\n\t\tfor(i = 3; i < argc; i++) {\n\t\t\tlink = sp_link_create_from_string(argv[i]);\n\t\t\tif(link == NULL || !(sp_link_type(link) == SP_LINKTYPE_TRACK || sp_link_type(link) == SP_LINKTYPE_LOCALTRACK))\n\t\t\t\tcontinue;\n\t\t\tsp_track_add_ref(tracks[num_tracks++] = sp_link_as_track(link));\n\t\t\tsp_link_release(link);\n\t\t}\n\t}\n\n\tif(num_tracks == 0) {\n\t\tfprintf(stderr, \"No valid tracks?\\n\");\n\t\treturn -1;\n\t}\n\n\treq = sp_inbox_post_tracks(g_session, argv[1], tracks, num_tracks,  argv[2], inbox_post_completed, NULL);\n\n\tfor(i = 0; i < num_tracks; i++)\n\t\tsp_track_release(tracks[i]);\n\tfree(tracks);\n\n\tif(req == NULL) {\n\t\tfprintf(stderr, \"inbox post failed\\n\");\n\t\treturn -1;\n\t}\n\n\treturn 0;\n}\n\n\n\n/**\n *\n */\nint cmd_inbox(int argc, char **argv)\n{\n\tsp_playlist *inbox;\n\tinbox = sp_session_inbox_create(g_session);\n\tif (!inbox) {\n\t\tprintf(\"Inbox not loaded\\n\");\n\t\treturn -1;\n\t}\n\tbrowse_playlist(inbox);\n\treturn 0;\n}\n"
  },
  {
    "path": "libspotify/examples/spshell/osx/spshell.xcodeproj/project.pbxproj",
    "content": "// !$*UTF8*$!\n{\n\tarchiveVersion = 1;\n\tclasses = {\n\t};\n\tobjectVersion = 45;\n\tobjects = {\n\n/* Begin PBXBuildFile section */\n\t\t0575285911634BB7003FFC9D /* star.c in Sources */ = {isa = PBXBuildFile; fileRef = 0575285811634BB7003FFC9D /* star.c */; };\n\t\t0575285D11634BC4003FFC9D /* social.c in Sources */ = {isa = PBXBuildFile; fileRef = 0575285C11634BC4003FFC9D /* social.c */; };\n\t\tCF513AC8115B722500662A82 /* appkey.c in Sources */ = {isa = PBXBuildFile; fileRef = CF513ABE115B722500662A82 /* appkey.c */; };\n\t\tCF513AC9115B722500662A82 /* browse.c in Sources */ = {isa = PBXBuildFile; fileRef = CF513ABF115B722500662A82 /* browse.c */; };\n\t\tCF513ACA115B722500662A82 /* cmd.c in Sources */ = {isa = PBXBuildFile; fileRef = CF513AC0115B722500662A82 /* cmd.c */; };\n\t\tCF513ACB115B722500662A82 /* inbox.c in Sources */ = {isa = PBXBuildFile; fileRef = CF513AC2115B722500662A82 /* inbox.c */; };\n\t\tCF513ACC115B722500662A82 /* search.c in Sources */ = {isa = PBXBuildFile; fileRef = CF513AC3115B722500662A82 /* search.c */; };\n\t\tCF513ACD115B722500662A82 /* spshell_posix.c in Sources */ = {isa = PBXBuildFile; fileRef = CF513AC4115B722500662A82 /* spshell_posix.c */; };\n\t\tCF513ACE115B722500662A82 /* spshell.c in Sources */ = {isa = PBXBuildFile; fileRef = CF513AC5115B722500662A82 /* spshell.c */; };\n\t\tCF513ACF115B722500662A82 /* toplist.c in Sources */ = {isa = PBXBuildFile; fileRef = CF513AC7115B722500662A82 /* toplist.c */; };\n\t\tCF513AD1115B722E00662A82 /* libspotify.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CF513AD0115B722E00662A82 /* libspotify.framework */; };\n\t\tCF513AF2115B73B900662A82 /* libreadline.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = CF513AF1115B73B900662A82 /* libreadline.dylib */; };\n/* End PBXBuildFile section */\n\n/* Begin PBXCopyFilesBuildPhase section */\n\t\t8DD76FAF0486AB0100D96B5E /* CopyFiles */ = {\n\t\t\tisa = PBXCopyFilesBuildPhase;\n\t\t\tbuildActionMask = 8;\n\t\t\tdstPath = /usr/share/man/man1/;\n\t\t\tdstSubfolderSpec = 0;\n\t\t\tfiles = (\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 1;\n\t\t};\n/* End PBXCopyFilesBuildPhase section */\n\n/* Begin PBXFileReference section */\n\t\t0575285811634BB7003FFC9D /* star.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = star.c; path = ../star.c; sourceTree = SOURCE_ROOT; };\n\t\t0575285C11634BC4003FFC9D /* social.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = social.c; path = ../social.c; sourceTree = SOURCE_ROOT; };\n\t\t8DD76FB20486AB0100D96B5E /* spshell */ = {isa = PBXFileReference; explicitFileType = \"compiled.mach-o.executable\"; includeInIndex = 0; path = spshell; sourceTree = BUILT_PRODUCTS_DIR; };\n\t\tCF513ABE115B722500662A82 /* appkey.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = appkey.c; path = ../../appkey.c; sourceTree = SOURCE_ROOT; };\n\t\tCF513ABF115B722500662A82 /* browse.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = browse.c; path = ../browse.c; sourceTree = SOURCE_ROOT; };\n\t\tCF513AC0115B722500662A82 /* cmd.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = cmd.c; path = ../cmd.c; sourceTree = SOURCE_ROOT; };\n\t\tCF513AC1115B722500662A82 /* cmd.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = cmd.h; path = ../cmd.h; sourceTree = SOURCE_ROOT; };\n\t\tCF513AC2115B722500662A82 /* inbox.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = inbox.c; path = ../inbox.c; sourceTree = SOURCE_ROOT; };\n\t\tCF513AC3115B722500662A82 /* search.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = search.c; path = ../search.c; sourceTree = SOURCE_ROOT; };\n\t\tCF513AC4115B722500662A82 /* spshell_posix.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = spshell_posix.c; path = ../spshell_posix.c; sourceTree = SOURCE_ROOT; };\n\t\tCF513AC5115B722500662A82 /* spshell.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = spshell.c; path = ../spshell.c; sourceTree = SOURCE_ROOT; };\n\t\tCF513AC6115B722500662A82 /* spshell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = spshell.h; path = ../spshell.h; sourceTree = SOURCE_ROOT; };\n\t\tCF513AC7115B722500662A82 /* toplist.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = toplist.c; path = ../toplist.c; sourceTree = SOURCE_ROOT; };\n\t\tCF513AD0115B722E00662A82 /* libspotify.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = libspotify.framework; path = /Library/Frameworks/libspotify.framework; sourceTree = \"<absolute>\"; };\n\t\tCF513AF1115B73B900662A82 /* libreadline.dylib */ = {isa = PBXFileReference; lastKnownFileType = \"compiled.mach-o.dylib\"; name = libreadline.dylib; path = usr/lib/libreadline.dylib; sourceTree = SDKROOT; };\n/* End PBXFileReference section */\n\n/* Begin PBXFrameworksBuildPhase section */\n\t\t8DD76FAD0486AB0100D96B5E /* Frameworks */ = {\n\t\t\tisa = PBXFrameworksBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\tCF513AD1115B722E00662A82 /* libspotify.framework in Frameworks */,\n\t\t\t\tCF513AF2115B73B900662A82 /* libreadline.dylib in Frameworks */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n/* End PBXFrameworksBuildPhase section */\n\n/* Begin PBXGroup section */\n\t\t08FB7794FE84155DC02AAC07 /* spshell */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t08FB7795FE84155DC02AAC07 /* Source */,\n\t\t\t\t1AB674ADFE9D54B511CA2CBB /* Products */,\n\t\t\t);\n\t\t\tname = spshell;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t08FB7795FE84155DC02AAC07 /* Source */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\tCF513ABE115B722500662A82 /* appkey.c */,\n\t\t\t\tCF513ABF115B722500662A82 /* browse.c */,\n\t\t\t\tCF513AC0115B722500662A82 /* cmd.c */,\n\t\t\t\tCF513AC1115B722500662A82 /* cmd.h */,\n\t\t\t\tCF513AC2115B722500662A82 /* inbox.c */,\n\t\t\t\tCF513AC3115B722500662A82 /* search.c */,\n\t\t\t\tCF513AC4115B722500662A82 /* spshell_posix.c */,\n\t\t\t\tCF513AC5115B722500662A82 /* spshell.c */,\n\t\t\t\tCF513AC6115B722500662A82 /* spshell.h */,\n\t\t\t\tCF513AC7115B722500662A82 /* toplist.c */,\n\t\t\t\t0575285811634BB7003FFC9D /* star.c */,\n\t\t\t\t0575285C11634BC4003FFC9D /* social.c */,\n\t\t\t);\n\t\t\tname = Source;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t1AB674ADFE9D54B511CA2CBB /* Products */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\tCF513AF1115B73B900662A82 /* libreadline.dylib */,\n\t\t\t\tCF513AD0115B722E00662A82 /* libspotify.framework */,\n\t\t\t\t8DD76FB20486AB0100D96B5E /* spshell */,\n\t\t\t);\n\t\t\tname = Products;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n/* End PBXGroup section */\n\n/* Begin PBXNativeTarget section */\n\t\t8DD76FA90486AB0100D96B5E /* spshell */ = {\n\t\t\tisa = PBXNativeTarget;\n\t\t\tbuildConfigurationList = 1DEB928508733DD80010E9CD /* Build configuration list for PBXNativeTarget \"spshell\" */;\n\t\t\tbuildPhases = (\n\t\t\t\t0575281D116348DB003FFC9D /* Ensure framework installation */,\n\t\t\t\t8DD76FAB0486AB0100D96B5E /* Sources */,\n\t\t\t\t8DD76FAD0486AB0100D96B5E /* Frameworks */,\n\t\t\t\t8DD76FAF0486AB0100D96B5E /* CopyFiles */,\n\t\t\t\t0575281F116348FB003FFC9D /* Change install name of libspotify */,\n\t\t\t);\n\t\t\tbuildRules = (\n\t\t\t);\n\t\t\tdependencies = (\n\t\t\t);\n\t\t\tname = spshell;\n\t\t\tproductInstallPath = \"$(HOME)/bin\";\n\t\t\tproductName = spshell;\n\t\t\tproductReference = 8DD76FB20486AB0100D96B5E /* spshell */;\n\t\t\tproductType = \"com.apple.product-type.tool\";\n\t\t};\n/* End PBXNativeTarget section */\n\n/* Begin PBXProject section */\n\t\t08FB7793FE84155DC02AAC07 /* Project object */ = {\n\t\t\tisa = PBXProject;\n\t\t\tbuildConfigurationList = 1DEB928908733DD80010E9CD /* Build configuration list for PBXProject \"spshell\" */;\n\t\t\tcompatibilityVersion = \"Xcode 3.1\";\n\t\t\thasScannedForEncodings = 1;\n\t\t\tmainGroup = 08FB7794FE84155DC02AAC07 /* spshell */;\n\t\t\tprojectDirPath = \"\";\n\t\t\tprojectRoot = \"\";\n\t\t\ttargets = (\n\t\t\t\t8DD76FA90486AB0100D96B5E /* spshell */,\n\t\t\t);\n\t\t};\n/* End PBXProject section */\n\n/* Begin PBXShellScriptBuildPhase section */\n\t\t0575281D116348DB003FFC9D /* Ensure framework installation */ = {\n\t\t\tisa = PBXShellScriptBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t);\n\t\t\tinputPaths = (\n\t\t\t);\n\t\t\tname = \"Ensure framework installation\";\n\t\t\toutputPaths = (\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t\tshellPath = /bin/sh;\n\t\t\tshellScript = \"if [ ! -e /Library/Frameworks/libspotify.framework ]; then\\n  echo \\\"You must install libspotify.framework to /Library/Frameworks.\\\" >&2\\n  exit 1\\nfi\\n\\nexit 0\";\n\t\t};\n\t\t0575281F116348FB003FFC9D /* Change install name of libspotify */ = {\n\t\t\tisa = PBXShellScriptBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t);\n\t\t\tinputPaths = (\n\t\t\t);\n\t\t\tname = \"Change install name of libspotify\";\n\t\t\toutputPaths = (\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t\tshellPath = /bin/sh;\n\t\t\tshellScript = \"install_name_tool -change @loader_path/../Frameworks/libspotify.framework/libspotify /Library/Frameworks/libspotify.framework/libspotify $CONFIGURATION_BUILD_DIR/$EXECUTABLE_PATH\";\n\t\t};\n/* End PBXShellScriptBuildPhase section */\n\n/* Begin PBXSourcesBuildPhase section */\n\t\t8DD76FAB0486AB0100D96B5E /* Sources */ = {\n\t\t\tisa = PBXSourcesBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\tCF513AC8115B722500662A82 /* appkey.c in Sources */,\n\t\t\t\tCF513AC9115B722500662A82 /* browse.c in Sources */,\n\t\t\t\tCF513ACA115B722500662A82 /* cmd.c in Sources */,\n\t\t\t\tCF513ACB115B722500662A82 /* inbox.c in Sources */,\n\t\t\t\tCF513ACC115B722500662A82 /* search.c in Sources */,\n\t\t\t\tCF513ACD115B722500662A82 /* spshell_posix.c in Sources */,\n\t\t\t\tCF513ACE115B722500662A82 /* spshell.c in Sources */,\n\t\t\t\tCF513ACF115B722500662A82 /* toplist.c in Sources */,\n\t\t\t\t0575285911634BB7003FFC9D /* star.c in Sources */,\n\t\t\t\t0575285D11634BC4003FFC9D /* social.c in Sources */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n/* End PBXSourcesBuildPhase section */\n\n/* Begin XCBuildConfiguration section */\n\t\t1DEB928608733DD80010E9CD /* Debug */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tALWAYS_SEARCH_USER_PATHS = NO;\n\t\t\t\tCOPY_PHASE_STRIP = NO;\n\t\t\t\tGCC_DYNAMIC_NO_PIC = NO;\n\t\t\t\tGCC_ENABLE_FIX_AND_CONTINUE = YES;\n\t\t\t\tGCC_MODEL_TUNING = G5;\n\t\t\t\tGCC_OPTIMIZATION_LEVEL = 0;\n\t\t\t\tINSTALL_PATH = /usr/local/bin;\n\t\t\t\tPRODUCT_NAME = spshell;\n\t\t\t};\n\t\t\tname = Debug;\n\t\t};\n\t\t1DEB928708733DD80010E9CD /* Release */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tALWAYS_SEARCH_USER_PATHS = NO;\n\t\t\t\tDEBUG_INFORMATION_FORMAT = \"dwarf-with-dsym\";\n\t\t\t\tFRAMEWORK_SEARCH_PATHS = (\n\t\t\t\t\t\"$(inherited)\",\n\t\t\t\t\t\"\\\"$(SRCROOT)/../../../..\\\"\",\n\t\t\t\t);\n\t\t\t\tGCC_MODEL_TUNING = G5;\n\t\t\t\tINSTALL_PATH = /usr/local/bin;\n\t\t\t\tPRODUCT_NAME = spshell;\n\t\t\t};\n\t\t\tname = Release;\n\t\t};\n\t\t1DEB928A08733DD80010E9CD /* Debug */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tARCHS = \"$(ARCHS_STANDARD_32_64_BIT)\";\n\t\t\t\tGCC_C_LANGUAGE_STANDARD = gnu99;\n\t\t\t\tGCC_OPTIMIZATION_LEVEL = 0;\n\t\t\t\tGCC_WARN_ABOUT_RETURN_TYPE = YES;\n\t\t\t\tGCC_WARN_UNUSED_VARIABLE = YES;\n\t\t\t\tONLY_ACTIVE_ARCH = YES;\n\t\t\t\tPREBINDING = NO;\n\t\t\t\tSDKROOT = macosx10.6;\n\t\t\t};\n\t\t\tname = Debug;\n\t\t};\n\t\t1DEB928B08733DD80010E9CD /* Release */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tARCHS = \"$(ARCHS_STANDARD_32_64_BIT)\";\n\t\t\t\tGCC_C_LANGUAGE_STANDARD = gnu99;\n\t\t\t\tGCC_WARN_ABOUT_RETURN_TYPE = YES;\n\t\t\t\tGCC_WARN_UNUSED_VARIABLE = YES;\n\t\t\t\tPREBINDING = NO;\n\t\t\t\tSDKROOT = macosx10.6;\n\t\t\t};\n\t\t\tname = Release;\n\t\t};\n/* End XCBuildConfiguration section */\n\n/* Begin XCConfigurationList section */\n\t\t1DEB928508733DD80010E9CD /* Build configuration list for PBXNativeTarget \"spshell\" */ = {\n\t\t\tisa = XCConfigurationList;\n\t\t\tbuildConfigurations = (\n\t\t\t\t1DEB928608733DD80010E9CD /* Debug */,\n\t\t\t\t1DEB928708733DD80010E9CD /* Release */,\n\t\t\t);\n\t\t\tdefaultConfigurationIsVisible = 0;\n\t\t\tdefaultConfigurationName = Release;\n\t\t};\n\t\t1DEB928908733DD80010E9CD /* Build configuration list for PBXProject \"spshell\" */ = {\n\t\t\tisa = XCConfigurationList;\n\t\t\tbuildConfigurations = (\n\t\t\t\t1DEB928A08733DD80010E9CD /* Debug */,\n\t\t\t\t1DEB928B08733DD80010E9CD /* Release */,\n\t\t\t);\n\t\t\tdefaultConfigurationIsVisible = 0;\n\t\t\tdefaultConfigurationName = Release;\n\t\t};\n/* End XCConfigurationList section */\n\t};\n\trootObject = 08FB7793FE84155DC02AAC07 /* Project object */;\n}\n"
  },
  {
    "path": "libspotify/examples/spshell/playlist.c",
    "content": "/**\n * Copyright (c) 2006-2010 Spotify Ltd\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n *\n */\n\n#include <string.h>\n\n#include \"spshell.h\"\n#include \"cmd.h\"\n\n#ifdef WIN32\n#define alloca _alloca\n#else\n#include <alloca.h>\n#endif\n\nstatic int subscriptions_updated;\n\n/**\n *\n */\nint cmd_update_subscriptions(int argc, char **argv)\n{\n\tint i;\n\tsp_playlistcontainer *pc = sp_session_playlistcontainer(g_session);\n\tsp_playlist *pl;\n\tsubscriptions_updated = 1;\n\tfor (i = 0; i < sp_playlistcontainer_num_playlists(pc); ++i) {\n\t\tswitch (sp_playlistcontainer_playlist_type(pc, i)) {\n\t\tcase SP_PLAYLIST_TYPE_PLAYLIST:\n\t\t\tpl = sp_playlistcontainer_playlist(pc, i);\n\t\t\tsp_playlist_update_subscribers(g_session, pl);\n\t\t\tbreak;\n\t\tdefault:\n\t\t\tbreak;\n\t\t}\n\t}\n\treturn 1;\n}\n\n\n\n/**\n *\n */\nint cmd_playlists(int argc, char **argv)\n{\n\tsp_playlistcontainer *pc = sp_session_playlistcontainer(g_session);\n\tint i, j, level = 0;\n\tsp_playlist *pl;\n\tchar name[200];\n\tint new = 0;\n\n\tprintf(\"%d entries in the container\\n\", sp_playlistcontainer_num_playlists(pc));\n\n\tfor (i = 0; i < sp_playlistcontainer_num_playlists(pc); ++i) {\n\t\tswitch (sp_playlistcontainer_playlist_type(pc, i)) {\n\t\t\tcase SP_PLAYLIST_TYPE_PLAYLIST:\n\t\t\t\tprintf(\"%d. \", i);\n\t\t\t\tfor (j = level; j; --j) printf(\"\\t\");\n\t\t\t\tpl = sp_playlistcontainer_playlist(pc, i);\n\t\t\t\tprintf(\"%s\", sp_playlist_name(pl));\n\t\t\t\tif(subscriptions_updated)\n\t\t\t\t\tprintf(\" (%d subscribers)\", sp_playlist_num_subscribers(pl));\n\n\t\t\t\tnew = sp_playlistcontainer_get_unseen_tracks(pc, pl, NULL, 0);\n\t\t\t\tif (new)\n\t\t\t\t\tprintf(\" (%d new)\", new);\n\n\t\t\t\tprintf(\"\\n\");\n\t\t\t\tbreak;\n\t\t\tcase SP_PLAYLIST_TYPE_START_FOLDER:\n\t\t\t\tprintf(\"%d. \", i);\n\t\t\t\tfor (j = level; j; --j) printf(\"\\t\");\n\t\t\t\tsp_playlistcontainer_playlist_folder_name(pc, i, name, sizeof(name));\n\t\t\t\tprintf(\"Folder: %s with id %llu\\n\", name,\n\t\t\t\t\t   sp_playlistcontainer_playlist_folder_id(pc, i));\n\t\t\t\tlevel++;\n\t\t\t\tbreak;\n\t\t\tcase SP_PLAYLIST_TYPE_END_FOLDER:\n\t\t\t\tlevel--;\n \t\t\t\tprintf(\"%d. \", i);\n\t\t\t\tfor (j = level; j; --j) printf(\"\\t\");\n\t\t\t\tprintf(\"End folder with id %llu\\n\",\tsp_playlistcontainer_playlist_folder_id(pc, i));\n\t\t\t\tbreak;\n\t\t\tcase SP_PLAYLIST_TYPE_PLACEHOLDER:\n\t\t\t\tprintf(\"%d. Placeholder\", i);\n\t\t\t\tbreak;\n\t\t}\n\t}\n\treturn 1;\n}\n\n/**\n *\n */\nstatic void print_track2(sp_track *track, int i)\n{\n\n\tprintf(\"%d. %c %s%s %s\\n\", i,\n\t       sp_track_is_starred(g_session, track) ? '*' : ' ',\n\t       sp_track_is_local(g_session, track) ? \"local\" : \"     \",\n\t       sp_track_is_autolinked(g_session, track) ? \"autolinked\" : \"          \",\n\t       sp_track_name(track));\n}\n\n\n/**\n *\n */\nint cmd_playlist(int argc, char **argv)\n{\n\tint index, i, nnew;\n\tsp_playlist *playlist;\n\tsp_playlistcontainer *pc = sp_session_playlistcontainer(g_session);\n\n\tif (argc < 1) {\n\t\tprintf(\"playlist [playlist index]\\n\");\n\t\treturn 0;\n\t}\n\n\tindex = atoi(argv[1]);\n\tif (index < 0 || index > sp_playlistcontainer_num_playlists(pc)) {\n\t\tprintf(\"invalid index\\n\");\n\t\treturn 0;\n\t}\n\n\tplaylist = sp_playlistcontainer_playlist(pc, index);\n\n\tnnew = sp_playlistcontainer_get_unseen_tracks(pc, playlist, 0, 0);\n\n\tprintf(\"Playlist %s by %s%s%s, %d new tracks\\n\",\n\t\t   sp_playlist_name(playlist),\n\t\t   sp_user_display_name(sp_playlist_owner(playlist)),\n\t\t   sp_playlist_is_collaborative(playlist) ? \" (collaborative)\" : \"\",\n\t           sp_playlist_has_pending_changes(playlist) ? \" with pending changes\" : \"\",\n\t           nnew\n\t\t   );\n\n\tif (argc == 3) {\n\t\tif (!strcmp(argv[2], \"new\")) {\n\t\t\tsp_track **tracks;\n\n\t\t\tif (nnew < 0)\n\t\t\t\treturn 1;\n\n\t\t\ttracks = alloca(nnew * sizeof(*tracks));\n\t\t\tsp_playlistcontainer_get_unseen_tracks(pc, playlist, tracks, nnew);\n\n\t\t\tfor (i = 0; i < nnew; i++) {\n\t\t\t\tprint_track2(tracks[i], i);\n\t\t\t}\n\t\t\treturn 1;\n\n\t\t} else if (!strcmp(argv[2], \"clear-unseen\"))\n\t\t\tsp_playlistcontainer_clear_unseen_tracks(pc, playlist);\n\n\t}\n\tfor (i = 0; i < sp_playlist_num_tracks(playlist); ++i) {\n\t\tsp_track *track = sp_playlist_track(playlist, i);\n\n\t\tprint_track2(track, i);\n\t}\n\treturn 1;\n}\n\n/**\n *\n */\nint cmd_set_autolink(int argc, char **argv)\n{\n\tint index; \n\tbool autolink;\n\tsp_playlist *playlist;\n\tsp_playlistcontainer *pc = sp_session_playlistcontainer(g_session);\n\n\tif (argc < 2) {\n\t\tprintf(\"set autolink [playlist index] [0/1]\\n\");\n\t\treturn 0;\n\t}\n\n\tindex = atoi(argv[1]);\n\tautolink = atoi(argv[2]);\n\tif (index < 0 || index > sp_playlistcontainer_num_playlists(pc)) {\n\t\tprintf(\"invalid index\\n\");\n\t\treturn 0;\n\t}\n\tplaylist = sp_playlistcontainer_playlist(pc, index);\n\tsp_playlist_set_autolink_tracks(playlist, !!autolink);\n\tprintf(\"Set autolinking to %s on playlist %s\\n\", autolink ? \"true\": \"false\", sp_playlist_name(playlist));\n\treturn 1;\n}\n\n\n\n/**\n *\n */\nint cmd_add_folder(int argc, char **argv)\n{\n\tint index; \n\tconst char *name;\n\tsp_playlistcontainer *pc = sp_session_playlistcontainer(g_session);\n\n\tif (argc < 2) {\n\t\tprintf(\"addfolder [playlist index] [name]\\n\");\n\t\treturn 0;\n\t}\n\n\tindex = atoi(argv[1]);\n\tname = argv[2];\n\n\tif (index < 0 || index > sp_playlistcontainer_num_playlists(pc)) {\n\t\tprintf(\"invalid index\\n\");\n\t\treturn 0;\n\t}\n\tsp_playlistcontainer_add_folder(pc, index, name);\n\treturn 1;\n}\n\n\nstatic sp_playlist_callbacks pl_update_callbacks;\n\n/**\n *\n */\nstruct pl_update_work {\n\tint position;\n\tint num_tracks;\n\tsp_track **tracks;\n};\n\nstatic int apply_changes(sp_playlist *pl, struct pl_update_work *puw)\n{\n\tsp_link *l;\n\tsp_error err;\n\n\tif(!sp_playlist_is_loaded(pl))\n\t\treturn 1;\n\n\n\tl = sp_link_create_from_playlist(pl);\n\tif(l == NULL)\n\t\treturn 1;\n\tsp_link_release(l);\n\n\tfprintf(stderr, \"Playlist loaded, applying changes ... \");\n\n\terr = sp_playlist_add_tracks(pl, puw->tracks,\n\t    puw->num_tracks, puw->position, g_session);\n\n\tswitch(err) {\n\tcase SP_ERROR_OK:\n\t\tfprintf(stderr, \"OK\\n\");\n\t\tbreak;\n\tcase SP_ERROR_INVALID_INDATA:\n\t\tfprintf(stderr, \"Invalid position\\n\");\n\t\tbreak;\n\n\tcase SP_ERROR_PERMISSION_DENIED:\n\t\tfprintf(stderr, \"Access denied\\n\");\n\t\tbreak;\n\tdefault:\n\t\tfprintf(stderr, \"Other error (should not happen)\\n\");\n\t\tbreak;\n\t}\n\treturn 0;\n}\n\nstatic void SP_CALLCONV pl_state_change(sp_playlist *pl, void *userdata)\n{\n\tstruct pl_update_work *puw = userdata;\n\tif(apply_changes(pl, puw))\n\t\treturn;\n\n\tsp_playlist_remove_callbacks(pl, &pl_update_callbacks, puw);\n\tsp_playlist_release(pl);\n\tcmd_done();\n}\n\nstatic sp_playlist_callbacks pl_update_callbacks = {\n\tNULL,\n\tNULL,\n\tNULL,\n\tNULL,\n\tpl_state_change,\n};\n\n\n/**\n *\n */\nint cmd_playlist_add_track(int argc, char **argv)\n{\n\tsp_link *plink, *tlink;\n\tsp_track *t;\n\tsp_playlist *pl;\n\tint i;\n\tstruct pl_update_work *puw;\n\n\tif(argc < 4) {\n\t\tprintf(\"add [playlist uri] [position] [track uri] <[track uri]>...\\n\");\n\t\treturn 1;\n\t}\n\n\tplink = sp_link_create_from_string(argv[1]);\n\tif (!plink) {\n\t\tfprintf(stderr, \"%s is not a spotify link\\n\", argv[1]);\n\t\treturn -1;\n\t}\n\n\tif(sp_link_type(plink) != SP_LINKTYPE_PLAYLIST) {\n\t\tfprintf(stderr, \"%s is not a playlist link\\n\", argv[1]);\n\t\tsp_link_release(plink);\n\t\treturn -1;\n\t}\n\n\tpuw = malloc(sizeof(struct pl_update_work));\n\tpuw->position = atoi(argv[2]);\n\tpuw->tracks = malloc(sizeof(sp_track *) * argc - 3);\n\tpuw->num_tracks = 0;\n\tfor(i = 0; i < argc - 3; i++) {\n\t\ttlink = sp_link_create_from_string(argv[i + 3]);\n\t\tif(tlink == NULL) {\n\t\t\tfprintf(stderr, \"%s is not a spotify link, skipping\\n\", argv[i + 3]);\n\t\t\tcontinue;\n\t\t}\n\t\tif(sp_link_type(tlink) != SP_LINKTYPE_TRACK) {\n\t\t\tfprintf(stderr, \"%s is not a track link, skipping\\n\", argv[i + 3]);\n\t\t\tcontinue;\n\t\t}\n\t\tt = sp_link_as_track(tlink);\n\t\tsp_track_add_ref(t);\n\t\tpuw->tracks[puw->num_tracks++] = t;\n\t\tsp_link_release(tlink);\n\t}\n\n\tpl = sp_playlist_create(g_session, plink);\n\tif(!apply_changes(pl, puw)) {\n\t\t// Changes applied directly, we're done\n\t\tsp_playlist_release(pl);\n\t\tsp_link_release(plink);\n\t\treturn 1;\n\t}\n\n\tfprintf(stderr, \"Playlist not yet loaded, waiting...\\n\");\n\tsp_playlist_add_callbacks(pl, &pl_update_callbacks, puw);\n\tsp_link_release(plink);\n\treturn 0;\n}\n\nstatic const char *offlinestatus[] = {\n\t\"None\",         // SP_PLAYLIST_OFFLINE_STATUS_NO\n\t\"Synchronized\", // SP_PLAYLIST_OFFLINE_STATUS_YES\n\t\"Downloading\",  // SP_PLAYLIST_OFFLINE_STATUS_DOWNLOADING\n\t\"Waiting\",      // SP_PLAYLIST_OFFLINE_STATUS_WAITING\n};\n\n\nint cmd_playlist_offline(int argc, char **argv)\n{\n\tsp_link *plink;\n\tsp_playlist *pl;\n\tint on;\n\n\tif (argc == 2 && !strcmp(argv[1], \"status\")) {\n\t\tprintf(\"Offline status\\n\");\n\t\tprintf(\"  %d tracks to sync\\n\",\n\t\t    sp_offline_tracks_to_sync(g_session));\n\t\tprintf(\"  %d offline playlists in total\\n\",\n\t\t    sp_offline_num_playlists(g_session));\n\t\treturn 1;\n\t}\n\n\n\tif (argc != 3) {\n\t\tprintf(\"offline status | <playlist uri> <on|off>\\n\");\n\t\treturn 1;\n\t}\n\n\n\tplink = sp_link_create_from_string(argv[1]);\n\tif (!plink) {\n\t\tfprintf(stderr, \"%s is not a spotify link\\n\", argv[1]);\n\t\treturn -1;\n\t}\n\n\tif (sp_link_type(plink) != SP_LINKTYPE_PLAYLIST) {\n\t\tfprintf(stderr, \"%s is not a playlist link\\n\", argv[1]);\n\t\tsp_link_release(plink);\n\t\treturn -1;\n\t}\n\n\n\tpl = sp_playlist_create(g_session, plink);\n\n\tif (argc == 3) {\n\n\t\tif (!strcasecmp(argv[2], \"on\"))\n\t\t\ton = 1;\n\t\telse if (!strcasecmp(argv[2], \"off\"))\n\t\t\ton = 0;\n\t\telse {\n\t\t\tfprintf(stderr, \"Invalid mode: %s\\n\", argv[2]);\n\t\t\treturn -1;\n\t\t}\n\n\t\tsp_playlist_set_offline_mode(g_session, pl, on);\n\n\t} else {\n\n\t\tsp_playlist_offline_status s;\n\t\ts = sp_playlist_get_offline_status(g_session, pl);\n\n\t\tprintf(\"Offline status for %s (%s)\\n\",\n\t\t    argv[1], sp_playlist_name(pl));\n\n\t\tprintf(\"  Status: %s\\n\", offlinestatus[s]);\n\t\tif (s == SP_PLAYLIST_OFFLINE_STATUS_DOWNLOADING)\n\t\t\tprintf(\"    %d%% Complete\\n\",\n\t\t\t    sp_playlist_get_offline_download_completed(g_session, pl));\n\t}\n\n\tsp_playlist_release(pl);\n\tsp_link_release(plink);\n\treturn 1;\n}\n"
  },
  {
    "path": "libspotify/examples/spshell/scrobbling.c",
    "content": "/**\n * Copyright (c) 2006-2012 Spotify Ltd\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n *\n */\n\n#include \"spshell.h\"\n#include <string.h>\n\nvoid print_scrobbling_state(sp_scrobbling_state state) {\n\tif (state == SP_SCROBBLING_STATE_LOCAL_ENABLED)\n\t\tprintf(\"locally overridden, enabled\");\n\telse if (state == SP_SCROBBLING_STATE_LOCAL_DISABLED)\n\t\tprintf(\"locally overridden, disabled\");\n\telse if (state == SP_SCROBBLING_STATE_GLOBAL_ENABLED)\n\t\tprintf(\"globally set, enabled\");\n\telse if (state == SP_SCROBBLING_STATE_GLOBAL_DISABLED)\n\t\tprintf(\"globally set, disabled\");\n\telse\n\t\tprintf(\"<unknown>\");\n}\n\n\nint cmd_facebook_scrobbling(int argc, char **argv)\n{\n\tif(argc != 2) {\n\t\tfprintf(stderr, \"facebook scrobbling local override enable|disable|unset\\n\");\n\t\treturn -1;\n\t}\n\n\tsp_scrobbling_state state = SP_SCROBBLING_STATE_USE_GLOBAL_SETTING;\n\tif (strcmp(argv[1], \"unset\")) {\n\t\t// not \"unset\"\n\t\tbool enable = !strcmp(argv[1], \"enable\");\n\t\tstate = enable ? SP_SCROBBLING_STATE_LOCAL_ENABLED : SP_SCROBBLING_STATE_LOCAL_DISABLED;\n\t}\n\tsp_session_set_scrobbling(g_session, SP_SOCIAL_PROVIDER_FACEBOOK, state);\n\n\treturn 1;\n}\n\nint cmd_is_facebook_scrobbling(int argc, char **argv)\n{\n\tprintf(\"facebook scrobbling state is \");\n\tsp_scrobbling_state state;\n\tsp_session_is_scrobbling(g_session, SP_SOCIAL_PROVIDER_FACEBOOK, &state);\n\tprint_scrobbling_state(state);\n\tprintf(\"\\n\");\n\treturn 1;\n}\n\nint cmd_spotify_social(int argc, char **argv)\n{\n\tif(argc != 2) {\n\t\tfprintf(stderr, \"spotify social local override enable|disable|unset\\n\");\n\t\treturn -1;\n\t}\n\n\tsp_scrobbling_state state = SP_SCROBBLING_STATE_USE_GLOBAL_SETTING;\n\tif (strcmp(argv[1], \"unset\")) {\n\t\t// not \"unset\"\n\t\tbool enable = !strcmp(argv[1], \"enable\");\n\t\tstate = enable ? SP_SCROBBLING_STATE_LOCAL_ENABLED : SP_SCROBBLING_STATE_LOCAL_DISABLED;\n\t}\n\tsp_session_set_scrobbling(g_session, SP_SOCIAL_PROVIDER_SPOTIFY, state);\n\n\treturn 1;\n}\n\nint cmd_is_spotify_social(int argc, char **argv)\n{\n\tprintf(\"spotify social scrobbling state is \");\n\tsp_scrobbling_state state;\n\tsp_session_is_scrobbling(g_session, SP_SOCIAL_PROVIDER_SPOTIFY, &state);\n\tprint_scrobbling_state(state);\n\tprintf(\"\\n\");\n\treturn 1;\n}\n\nint cmd_set_lastfm_scrobbling_credentials(int argc, char **argv)\n{\n\tif(argc != 3) {\n\t\tfprintf(stderr, \"lastfm_scrobbling_credentials username password\\n\");\n\t\treturn -1;\n\t}\n\n\tsp_session_set_social_credentials(g_session, SP_SOCIAL_PROVIDER_LASTFM, argv[1], argv[2]);\n\treturn 1;\n}\n\nint cmd_lastfm_scrobbling(int argc, char **argv)\n{\n\tif(argc != 2) {\n\t\tfprintf(stderr, \"lastfm_scrobbling enable|disable\\n\");\n\t\treturn -1;\n\t}\n\n\tbool enable = !strcmp(argv[1], \"enable\");\n\tsp_scrobbling_state state = enable ? SP_SCROBBLING_STATE_LOCAL_ENABLED : SP_SCROBBLING_STATE_LOCAL_DISABLED;\n\n\tsp_session_set_scrobbling(g_session, SP_SOCIAL_PROVIDER_LASTFM, state);\n\treturn 1;\n}\n\nint cmd_is_lastfm_scrobbling(int argc, char **argv)\n{\n\tprintf(\"lastfm scrobbling state is \");\n\tsp_scrobbling_state state;\n\tsp_session_is_scrobbling(g_session, SP_SOCIAL_PROVIDER_LASTFM, &state);\n\n\tif (state == SP_SCROBBLING_STATE_LOCAL_ENABLED)\n\t\tprintf(\"enabled\");\n\telse if (state == SP_SCROBBLING_STATE_LOCAL_DISABLED)\n\t\tprintf(\"disabled\");\n\telse\n\t\tprintf(\"<unknown>\");\n\n\tprintf(\"\\n\");\n\treturn 1;\n}\n\nextern int cmd_private_session(int argc, char** argv)\n{\n\tif(argc != 2) {\n\t\tfprintf(stderr, \"private_session enable|disable\\n\");\n\t\treturn -1;\n\t}\n\n\tsp_session_set_private_session(g_session, !strcmp(argv[1], \"enable\"));\n\treturn 1;\n}\n\nextern int cmd_is_private_session(int argc, char** argv)\n{\n\tprintf(\"private_session is \");\n\tprintf( sp_session_is_private_session(g_session) ? \"enabled\" : \"disabled\");\n\tprintf(\"\\n\");\n\treturn 1;\n}\n\n"
  },
  {
    "path": "libspotify/examples/spshell/search.c",
    "content": "/**\n * Copyright (c) 2006-2010 Spotify Ltd\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n *\n */\n\n#include <string.h>\n\n#include \"spshell.h\"\n#include \"cmd.h\"\n\n\n/**\n * Print the given album metadata\n *\n * @param  album  The album object\n */\nstatic void print_album(sp_album *album)\n{\n\tprintf(\"  Album \\\"%s\\\" (%d)\\n\",\n\t       sp_album_name(album),\n\t       sp_album_year(album));\n}\n\n/**\n * Print the given artist metadata\n *\n * @param  artist  The artist object\n */\nstatic void print_artist(sp_artist *artist)\n{\n\tprintf(\"  Artist \\\"%s\\\"\\n\", sp_artist_name(artist));\n}\n\n/**\n * Print the given search result with as much information as possible\n *\n * @param  search   The search result\n */\nstatic void print_search(sp_search *search)\n{\n\tint i;\n\n\tprintf(\"Query          : %s\\n\", sp_search_query(search));\n\tprintf(\"Did you mean   : %s\\n\", sp_search_did_you_mean(search));\n\tprintf(\"Tracks in total: %d\\n\", sp_search_total_tracks(search));\n\tputs(\"\");\n\n\tfor (i = 0; i < sp_search_num_tracks(search); ++i)\n\t\tprint_track(sp_search_track(search, i));\n\n\tputs(\"\");\n\n\tfor (i = 0; i < sp_search_num_albums(search); ++i)\n\t\tprint_album(sp_search_album(search, i));\n\n\tputs(\"\");\n\n\tfor (i = 0; i < sp_search_num_artists(search); ++i)\n\t\tprint_artist(sp_search_artist(search, i));\n\n\tputs(\"\");\n\n\tfor (i = 0; i < sp_search_num_playlists(search); ++i) {\n\t\t// print some readily available metadata, the rest will\n\t\t// be available from the sp_playlist object loaded through\n\t\t// sp_search_playlist().\n\t\tprintf(\"  Playlist \\\"%s\\\"\\n\", sp_search_playlist_name(search, i));\n\t}\n}\n\n/**\n * Callback for libspotify\n *\n * @param browse    The browse result object that is now done\n * @param userdata  The opaque pointer given to sp_artistbrowse_create()\n */\nstatic void SP_CALLCONV search_complete(sp_search *search, void *userdata)\n{\n\tif (sp_search_error(search) == SP_ERROR_OK)\n\t\tprint_search(search);\n\telse\n\t\tfprintf(stderr, \"Failed to search: %s\\n\",\n\t\t        sp_error_message(sp_search_error(search)));\n\n\tsp_search_release(search);\n\tcmd_done();\n}\n\n\n\n/**\n *\n */\nstatic void search_usage(void)\n{\n\tfprintf(stderr, \"Usage: search <query>\\n\");\n}\n\n\n/**\n *\n */\nint cmd_search(int argc, char **argv)\n{\n\tchar query[1024];\n\tint i;\n\n\tif (argc < 2) {\n\t\tsearch_usage();\n\t\treturn -1;\n\t}\n\n\tquery[0] = 0;\n\tfor(i = 1; i < argc; i++)\n\t\tsnprintf(query + strlen(query), sizeof(query) - strlen(query), \"%s%s\",\n\t\t\t i == 1 ? \"\" : \" \", argv[i]);\n\n\tsp_search_create(g_session, query, 0, 100, 0, 100, 0, 100, 0, 100, SP_SEARCH_STANDARD, &search_complete, NULL);\n\treturn 0;\n}\n\n\n/**\n *\n */\nint cmd_whatsnew(int argc, char **argv)\n{\n\tsp_search_create(g_session, \"tag:new\", 0, 0, 0, 250, 0, 0, 0, 0, SP_SEARCH_STANDARD, &search_complete, NULL);\n\treturn 0;\n}\n"
  },
  {
    "path": "libspotify/examples/spshell/spshell.c",
    "content": "/**\n * Copyright (c) 2006-2010 Spotify Ltd\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n *\n */\n\n#include <string.h>\n\n#include \"spshell.h\"\n#include \"cmd.h\"\n\nsp_session *g_session;\nvoid (*metadata_updated_fn)(void);\nint is_logged_out;\nint log_to_stderr;\nint g_selftest;\n\n\n/**\n * This callback is called when the user was logged in, but the connection to\n * Spotify was dropped for some reason.\n *\n * @sa sp_session_callbacks#connection_error\n */\nstatic void SP_CALLCONV connection_error(sp_session *session, sp_error error)\n{\n\tfprintf(stderr, \"Connection to Spotify failed: %s\\n\",\n\t                sp_error_message(error));\n}\n\n/**\n * This callback is called when an attempt to login has succeeded or failed.\n *\n * @sa sp_session_callbacks#logged_in\n */\nstatic void SP_CALLCONV logged_in(sp_session *session, sp_error error)\n{\n\tsp_user *me;\n\tconst char *display_name, *username;\n\tint cc;\n\n\tif (SP_ERROR_OK != error) {\n\t\tfprintf(stderr, \"failed to log in to Spotify: %s\\n\",\n\t\t                sp_error_message(error));\n\t\tsp_session_release(session);\n\t\texit(4);\n\t}\n\n\t// Let us print the nice message...\n\tme = sp_session_user(session);\n\tdisplay_name = (sp_user_is_loaded(me) ? sp_user_display_name(me) : sp_user_canonical_name(me));\n\tusername = sp_session_user_name (session);\n\tcc = sp_session_user_country(session);\n\tfprintf(stderr, \"Logged in to Spotify as user %s [%s] (registered in country: %c%c)\\n\", username, display_name, cc >> 8, cc & 0xff);\n\n#if WITH_TEST_COMMAND\n\tif(g_selftest)\n\t\tcmd_test(0, NULL);\n\telse\n#endif\n\t\tstart_prompt();\n}\n\n/**\n * This callback is called when the session has logged out of Spotify.\n *\n * @sa sp_session_callbacks#logged_out\n */\nstatic void SP_CALLCONV logged_out(sp_session *session)\n{\n\tis_logged_out = 1;  // Will exit mainloop\n}\n\n#ifdef SP_LIBSPOTIFY_WITH_SCROBBLING\n/**\n * This callback is called when there is a scrobble error.\n *\n * @sa sp_session_callbacks#scrobble_error\n */\nstatic void SP_CALLCONV scrobble_error(sp_session* session, sp_error error) {\n\tfprintf(stderr, \"Scrobble failure: %d\\n\", error);\n}\n\n/**\n * Called when there is a change in the private session mode\n *\n * @param[in]  session    Session\n * @param[in]  isPrivate  True if in private session, false otherwhise\n */\nstatic void SP_CALLCONV private_session_mode_changed(sp_session *session, bool is_private) {\n\tprintf(\"private session mode changed: %d\\n\", is_private);\n}\n#endif\n\n/**\n * This callback is called when the session have recieved a credential\n * that could be stored safely on disk\n *\n * @sa sp_session_callbacks#credentials_blob_updated\n */\nstatic void SP_CALLCONV credentials_blob_updated(sp_session *session, const char *blob)\n{\n\tprintf(\"blob for storage: %s\\n\", blob);\n}\n\n/**\n * This callback is called for log messages.\n *\n * @sa sp_session_callbacks#log_message\n */\nstatic void SP_CALLCONV log_message(sp_session *session, const char *data)\n{\n\tif (log_to_stderr)\n\t\tfprintf(stderr, \"%s\", data);\n}\n\n\n\n/**\n * Callback called when libspotify has new metadata available\n *\n * Not used in this example (but available to be able to reuse the session.c file\n * for other examples.)\n *\n * @sa sp_session_callbacks#metadata_updated\n */\nstatic void SP_CALLCONV metadata_updated(sp_session *sess)\n{\n\tif(metadata_updated_fn)\n\t\tmetadata_updated_fn();\n#if WITH_TEST_COMMAND\n\tif(g_selftest)\n\t\ttest_process();\n#endif\n}\n\n\n/**\n *\n */\nstatic void SP_CALLCONV offline_status_updated(sp_session *sess)\n{\n\tsp_offline_sync_status status;\n\tsp_offline_sync_get_status(sess, &status);\n\tif(status.syncing) {\n\t\tprintf(\"Offline status: queued:%d:%zd done:%d:%zd copied:%d:%zd nocopy:%d err:%d\\n\",\n\t\t    status.queued_tracks,\n\t\t    (size_t)status.queued_bytes,\n\t\t    status.done_tracks,\n\t\t    (size_t)status.done_bytes,\n\t\t    status.copied_tracks,\n\t\t    (size_t)status.copied_bytes,\n\t\t    status.willnotcopy_tracks,\n\t\t    status.error_tracks);\n\t} else {\n\t\tprintf(\"Offline status: Idle\\n\");\n\t}\n}\n\n/**\n * Session callbacks\n */\n\nstatic sp_session_callbacks callbacks;\n\n/**\n *\n */\nint spshell_init(const char *username, const char *password, const  char *blob, int selftest)\n{\n\tsp_session_config config;\n\tsp_error error;\n\tsp_session *session;\n\n        /// The application key is specific to each project, and allows Spotify\n        /// to produce statistics on how our service is used.\n\textern const char g_appkey[];\n        /// The size of the application key.\n\textern const size_t g_appkey_size;\n\n\tg_selftest = selftest;\n\n\tmemset(&config, 0, sizeof(config));\n\n\t// Always do this. It allows libspotify to check for\n\t// header/library inconsistencies.\n\tconfig.api_version = SPOTIFY_API_VERSION;\n\n\t// The path of the directory to store the cache. This must be specified.\n\t// Please read the documentation on preferred values.\n\tconfig.cache_location = selftest ? \"\" : \"tmp\";\n\n\t// The path of the directory to store the settings. \n\t// This must be specified.\n\t// Please read the documentation on preferred values.\n\tconfig.settings_location = selftest ? \"\" : \"tmp\";\n\n\t// The key of the application. They are generated by Spotify,\n\t// and are specific to each application using libspotify.\n\tconfig.application_key = g_appkey;\n\tconfig.application_key_size = g_appkey_size;\n\n\t// This identifies the application using some\n\t// free-text string [1, 255] characters.\n\tconfig.user_agent = \"spshell\";\n\n\n\t// Register the callbacks.\n\tcallbacks.logged_in = logged_in;\n\tcallbacks.logged_out = logged_out;\n\tcallbacks.metadata_updated = metadata_updated;\n\tcallbacks.connection_error = connection_error;\n\tcallbacks.notify_main_thread = notify_main_thread;\n#if WITH_TEST_COMMAND\n\tcallbacks.music_delivery = music_delivery;\n\tcallbacks.play_token_lost = play_token_lost;\n\tcallbacks.end_of_track = end_of_track;\n#endif\n\tcallbacks.log_message = log_message;\n\tcallbacks.offline_status_updated = offline_status_updated;\n\tcallbacks.credentials_blob_updated = credentials_blob_updated;\n#ifdef SP_LIBSPOTIFY_WITH_SCROBBLING\n\tcallbacks.scrobble_error = scrobble_error;\n\tcallbacks.private_session_mode_changed = private_session_mode_changed;\n#endif\n\tconfig.callbacks = &callbacks;\n\n\terror = sp_session_create(&config, &session);\n\tif (SP_ERROR_OK != error) {\n\t\tfprintf(stderr, \"failed to create session: %s\\n\",\n\t\t                sp_error_message(error));\n\t\treturn 2;\n\t}\n\n\t// Login using the credentials given on the command line.\n\tif (username == NULL) {\n\t\tchar reloginname[256];\n\n\t\tif (sp_session_relogin(session) == SP_ERROR_NO_CREDENTIALS) {\n\t\t\tfprintf(stderr, \"No stored credentials\\n\");\n\t\t\treturn 3;\n\t\t}\n\t\tsp_session_remembered_user(session, reloginname, sizeof(reloginname));\n\t\tfprintf(stderr, \"Trying to relogin as user %s\\n\", reloginname);\n\n\t} else {\n\t\tsp_session_login(session, username, password, 1, blob);\n\t}\n\n\tg_session = session;\n\treturn 0;\n}\n\n\n/**\n *\n */\nint cmd_logout(int argc, char **argv)\n{\n\tif(argc == 2 && !strcmp(argv[1], \"permanent\")) {\n\t\tfprintf(stderr, \"Dropping stored credentials\\n\");\n\t\tsp_session_forget_me(g_session);\n\t}\n\tsp_session_logout(g_session);\n\treturn 0;\n}\n\n\n/**\n *\n */\nvoid test_finished(void)\n{\n\tcmd_logout(0, NULL);\n}\n\n/**\n *\n */\nint cmd_log(int argc, char **argv)\n{\n\tif(argc != 2) {\n\t\tfprintf(stderr, \"log enable|disable\\n\");\n\t\treturn -1;\n\t}\n\n\tlog_to_stderr = !strcmp(argv[1], \"enable\");\n\treturn 1;\n}\n"
  },
  {
    "path": "libspotify/examples/spshell/spshell.h",
    "content": "/**\n * Copyright (c) 2006-2010 Spotify Ltd\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n *\n */\n\n#ifndef SPSHELL_H__\n#define SPSHELL_H__\n\n#include <stdlib.h>\n#ifndef WIN32\n#include <stdint.h>\n#endif\n#include <stdio.h>\n#include <libspotify/api.h>\n\n#define WITH_TEST_COMMAND 1\n\n#if WIN32\n#include <windows.h>\n#define snprintf sprintf_s\n#define strcasecmp lstrcmp\n#endif \n\n#ifndef PRIx64\n#define PRIx64 \"llx\"\n#endif\n\n#if USE_STRCMP\n#define strcasecmp strcmp\n#endif\n\nextern sp_session *g_session;\n\nextern void (*metadata_updated_fn)(void);\n\nextern int spshell_init(const char *username, const char *password, const char *blob, int selftest);\n\nextern void SP_CALLCONV notify_main_thread(sp_session *session);\n\nextern void start_prompt(void);\n\nextern sp_uint64 get_ts(void);\n\n#if WITH_TEST_COMMAND\n\nextern void test_finished(void);\n\nextern void test_process(void);\n\nextern void SP_CALLCONV end_of_track(sp_session *s);\n\nextern int SP_CALLCONV music_delivery(sp_session *s, const sp_audioformat *fmt, const void *frames, int num_frames);\n\nextern void SP_CALLCONV play_token_lost(sp_session *s);\n\n#endif\n\n#endif // SPSHELL_H__\n"
  },
  {
    "path": "libspotify/examples/spshell/spshell_posix.c",
    "content": "/**\n * Copyright (c) 2006-2010 Spotify Ltd\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n *\n */\n\n#include <unistd.h>\n#include <pthread.h>\n#include <stdio.h>\n#include <string.h>\n#include <sys/time.h>\n\n#include <readline/readline.h>\n#include <readline/history.h>\n\n#include \"spshell.h\"\n#include \"cmd.h\"\n\n/// Set when libspotify want to process events\nstatic int notify_events;\n\n/// Synchronization mutex to protect various shared data\nstatic pthread_mutex_t notify_mutex;\n\n/// Synchronization condition variable for the main thread\nstatic pthread_cond_t notify_cond;\n\n/// Synchronization condition variable to disable prompt temporarily\nstatic pthread_cond_t prompt_cond;\n\n/// Command line to execute\nstatic char *cmdline;\n\n/// \nstatic int show_prompt;\n\nextern int is_logged_out;\n\nextern int g_selftest;\n\n/**\n *\n */\nstatic void *promptloop(void *aux)\n{\n\tpthread_mutex_lock(&notify_mutex);\n\n\twhile(1) {\n\t\tchar *l;\n\n\t\twhile(show_prompt == 0)\n\t\t\tpthread_cond_wait(&prompt_cond, &notify_mutex);\n\n\t\tpthread_mutex_unlock(&notify_mutex);\n\t\tl = readline(\"> \");\n\t\tpthread_mutex_lock(&notify_mutex);\n\n\t\tshow_prompt = 0;\n\t\tcmdline = l;\n\t\tpthread_cond_signal(&notify_cond);\n\t}\n\treturn NULL;\n}\n\n\n/**\n *\n */\nvoid start_prompt(void)\n{\n\tstatic pthread_t id;\n\tif (id)\n\t\treturn;\n\tshow_prompt = 1;\n\tpthread_create(&id, NULL, promptloop, NULL);\n}\n\n\n\n/**\n *\n */\nstatic void trim(char *buf)\n{\n\tsize_t l = strlen(buf);\n\twhile(l > 0 && buf[l - 1] < 32)\n\t\tbuf[--l] = 0;\n}\n\n\n/**\n *\n */\nint main(int argc, char **argv)\n{\n\tconst char *username = NULL;\n\tconst char *blob = NULL;\n\tconst char *password = NULL;\n\tint selftest = 0;\n\tchar username_buf[256];\n\tint r;\n\tint next_timeout = 0;\n\tint ch;\n\n\tprintf(\"Using libspotify %s\\n\", sp_build_id());\n\tr = 0;\n\twhile ((ch = getopt(argc, argv, \"tb:u:p:\")) != -1) {\n\n\t\tswitch (ch) {\n\t\tcase 'u':\n\t\t  \tusername = optarg;\n\t\t\tbreak;\n\t\tcase 'p':\n\t\t  \tpassword = optarg;\n\t\t\tbreak;\n\t\tcase 'b':\n\t\t\tblob = optarg;\n\t\t\tr +=2;\n\t\t\tbreak;\n\t\tcase 't':\n\t\t\tselftest = 1;\n\t\t\tr++;\n\t\t\tbreak;\n\t\tdefault:\n\t\t\tbreak;\n\t\t}\n\t}\n\n\tif (username == NULL) {\n\t\tprintf(\"Username (just press enter to login with stored credentials): \");\n\t\tfflush(stdout);\n\t\tfgets(username_buf, sizeof(username_buf), stdin);\n\t\ttrim(username_buf);\n\t\tif(username_buf[0] == 0) {\n\t\t\tusername = NULL;\n\t\t} else {\n\t\t\tusername = username_buf;\n\t\t}\n\t}\n\n\t// If a username was supplied but no blob, prompt for password\n\tif (username != NULL && password == NULL && blob == NULL)\n\t\tpassword = getpass(\"Password: \");\n\n\tpthread_mutex_init(&notify_mutex, NULL);\n\tpthread_cond_init(&notify_cond, NULL);\n\tpthread_cond_init(&prompt_cond, NULL);\n\n\tif ((r = spshell_init(username, password, blob, selftest)) != 0)\n\t\texit(r);\n\n\tpthread_mutex_lock(&notify_mutex);\n\n\twhile(!is_logged_out) {\n\t\t// Release prompt\n\t\tif (next_timeout == 0) {\n\t\t\twhile(!notify_events && !cmdline)\n\t\t\t\tpthread_cond_wait(&notify_cond, &notify_mutex);\n\t\t} else {\n\t\t\tstruct timespec ts;\n\n#if _POSIX_TIMERS > 0\n\t\t\tclock_gettime(CLOCK_REALTIME, &ts);\n#else\n\t\t\tstruct timeval tv;\n\t\t\tgettimeofday(&tv, NULL);\n\t\t\tTIMEVAL_TO_TIMESPEC(&tv, &ts);\n#endif\n\n\t\t\tts.tv_sec += next_timeout / 1000;\n\t\t\tts.tv_nsec += (next_timeout % 1000) * 1000000;\n\t\t\tif(ts.tv_nsec > 1000000000) {\n\t\t\t\tts.tv_sec ++;\n\t\t\t\tts.tv_nsec -= 1000000000;\n\t\t\t}\n\n\n\t\t\twhile(!notify_events && !cmdline) {\n\t\t\t\tif(pthread_cond_timedwait(&notify_cond, &notify_mutex, &ts))\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\t// Process input from prompt\n\t\tif(cmdline) {\n\t\t\tchar *l = cmdline;\n\t\t\tcmdline = NULL;\n\t\t\n\t\t\tpthread_mutex_unlock(&notify_mutex);\n\t\t\tcmd_exec_unparsed(l);\n\t\t\tfree(l);\n\t\t\tpthread_mutex_lock(&notify_mutex);\n\t\t}\n\n\t\t// Process libspotify events\n\t\tnotify_events = 0;\n\t\tpthread_mutex_unlock(&notify_mutex);\n\n\t\tdo {\n\t\t\tsp_session_process_events(g_session, &next_timeout);\n\t\t} while (next_timeout == 0);\n\n\t\tif(g_selftest)\n\t\t\ttest_process();\n\n\t\tpthread_mutex_lock(&notify_mutex);\n\t}\n\tprintf(\"Logged out\\n\");\n\tsp_session_release(g_session);\n\tprintf(\"Exiting...\\n\");\n\treturn 0;\n}\n\n/**\n *\n */\nvoid cmd_done(void)\n{\n\tpthread_mutex_lock(&notify_mutex);\n\tshow_prompt = 1;\n\tpthread_cond_signal(&prompt_cond);\n\tpthread_mutex_unlock(&notify_mutex);\n}\n\n\n/**\n *\n */\nvoid notify_main_thread(sp_session *session)\n{\n\tpthread_mutex_lock(&notify_mutex);\n\tnotify_events = 1;\n\tpthread_cond_signal(&notify_cond);\n\tpthread_mutex_unlock(&notify_mutex);\n}\n\n\n/**\n *\n */\nsp_uint64 get_ts(void)\n{\n\tstruct timeval tv;\n\tgettimeofday(&tv, NULL);\n\treturn (int64_t)tv.tv_sec * 1000LL + (tv.tv_usec / 1000);\n}\n"
  },
  {
    "path": "libspotify/examples/spshell/spshell_win32.c",
    "content": "/**\n * Copyright (c) 2006-2010 Spotify Ltd\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n *\n */\n\n#include \"spshell.h\"\n#include \"cmd.h\"\n\nstatic HANDLE events[2];\n\nstatic int enable_console;\nstatic char console_buf[1024];\nstatic int console_ptr;\n\nextern int is_logged_out;\n\nextern int g_selftest;\n\n/**\n * Very simplistic console input\n */\nstatic void console_input(void)\n{\n\tTCHAR inp;\n\tDWORD read;\n\tINPUT_RECORD rec;\n\n\tif(!ReadConsoleInput(events[1], &rec, 1, &read))\n\t\treturn;\n\n\tif(read == 0)\n\t\treturn;\n\n\tif(rec.EventType != KEY_EVENT)\n\t\treturn;\n\n\tif(!rec.Event.KeyEvent.bKeyDown)\n\t\treturn;\n\n\tinp = rec.Event.KeyEvent.uChar.AsciiChar;\n\n\n\tswitch(inp) {\n\tcase 8:\n\t\tif(console_ptr > 0) {\n\t\t\tconsole_ptr--;\n\t\t\tprintf(\"\\b \\b\");\n\t\t}\n\t\tbreak;\n\tcase 13:\n\t\tprintf(\"\\n\\r\");\n\t\tconsole_buf[console_ptr++] = 0;\n\t\tconsole_ptr = 0;\n\t\tenable_console = 0;\n\t\tcmd_exec_unparsed(console_buf);\n\t\tbreak;\n\n\tdefault:\n\t\tif(console_ptr < sizeof(console_buf) - 1) {\n\t\t\tprintf(\"%c\", (char)inp);\n\t\t\tconsole_buf[console_ptr++] = inp;\n\t\t}\n\t\tbreak;\n\t}\n}\n\nstatic void trim(char *buf)\n{\n\tsize_t l = strlen(buf);\n\twhile(l > 0 && buf[l - 1] < 32)\n\t\tbuf[--l] = 0;\n}\n\n\nint __cdecl main(int argc, char **argv)\n{\n\tconst char *username = argc > 1 ? argv[1] : NULL;\n\tconst char *blob = argc > 2 ? argv[2] : NULL;\n\tconst char *password = NULL;\n\tint selftest = argc > 3 ? !strcmp(argv[3], \"selftest\") : 0;\n\tchar username_buf[256];\n\tchar password_buf[256];\n\tint r;\n\tint next_timeout = 0;\n\tDWORD ev;\n\tDWORD mode;\n\n\tevents[0] = CreateEvent(NULL, FALSE, FALSE, NULL);\n\tevents[1] = GetStdHandle(STD_INPUT_HANDLE);\n\n\tprintf(\"Using libspotify %s\\n\", sp_build_id());\n\n\tif (username == NULL) {\n\t\tprintf(\"Username: (just press enter to login with stored credentials): \");\n\t\tfflush(stdout);\n\t\tfgets(username_buf, sizeof(username_buf), stdin);\n\t\ttrim(username_buf);\n\t\tif(username_buf[0] == 0) {\n\t\t\tusername = NULL;\n\t\t} else {\n\t\t\tusername = username_buf;\n\t\t}\n\t}\n\n\t// If a username was supplied but no blob, prompt for password\n\tif (username != NULL && blob == NULL) {\n\t\tprintf(\"Password: \");\n\t\tfflush(stdout);\n\n\t\tif (!GetConsoleMode(events[1], &mode) ||\n\t\t\t!SetConsoleMode(events[1], mode & ~ENABLE_ECHO_INPUT)) {\n\t\t\tprintf(\"Unable to set console mode err=%d\\n\", GetLastError());\n\t\t\texit(1);\n\t\t}\n\n\t\tfgets(password_buf, sizeof(password_buf), stdin);\n\t\ttrim(password_buf);\n\t\tpassword = password_buf;\n\t\tprintf(\"\\r\\n\");\n\t}\n\n\tif ((r = spshell_init(username, password, blob, selftest)) != 0)\n\t\texit(r);\n\n\tif (!SetConsoleMode(events[1], ENABLE_PROCESSED_INPUT)) {\n\t\tprintf(\"Unable to set console mode err=%d\\n\", GetLastError());\n\t\texit(1);\n\t}\n\n\twhile(!is_logged_out) {\n\t\tev = WaitForMultipleObjects(1 + enable_console, events, FALSE, next_timeout > 0 ? next_timeout : INFINITE);\n\t\tswitch (ev) {\n\t\tcase WAIT_OBJECT_0 + 0:\n\t\tcase WAIT_TIMEOUT:\n\t\t\tdo {\n\t\t\t\tsp_session_process_events(g_session, &next_timeout);\n\t\t\t} while (next_timeout == 0);\n\n\t\t\tif(g_selftest)\n\t\t\t\ttest_process();\n\t\t\tbreak;\n\n\t\tcase WAIT_OBJECT_0 + 1:\n\t\t\tconsole_input();\n\t\t\tbreak;\n\t\t}\n\t}\n\tprintf(\"Logged out\\n\");\n\tsp_session_release(g_session);\n\tprintf(\"Exiting...\\n\");\n\treturn 0;\n}\n\n/**\n *\n */\nvoid cmd_done(void)\n{\n\tenable_console = 1;\n\tprintf(\"> \");\n\tfflush(stdout);\n}\n\n\n/**\n *\n */\nvoid start_prompt(void)\n{\n\tcmd_done();\n}\n\n\n/**\n *\n */\nvoid SP_CALLCONV notify_main_thread(sp_session *session)\n{\n\tSetEvent(events[0]);\n}\n\n/**\n *\n */\nsp_uint64 get_ts(void)\n{\n\treturn GetTickCount();\n}\n"
  },
  {
    "path": "libspotify/examples/spshell/star.c",
    "content": "/**\n * Copyright (c) 2006-2010 Spotify Ltd\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n *\n */\n\n#include \"spshell.h\"\n#include \"cmd.h\"\n\n/**\n *\n */\nstatic void star_usage(const char *prefix)\n{\n\tfprintf(stderr, \"Usage: %sstar <track-uri>\\n\", prefix);\n}\n\n\n/**\n *\n */\nstatic int dostar(int argc, char **argv, int set)\n{\n\tsp_link *link;\n\tsp_track *track;\n\n\tif (argc != 2) {\n\t\tstar_usage(set ? \"\" : \"un\");\n\t\treturn -1;\n\t}\n\t\n\tlink = sp_link_create_from_string(argv[1]);\n\t\n\tif (!link) {\n\t\tfprintf(stderr, \"Not a spotify link\\n\");\n\t\treturn -1;\n\t}\n\n\tif (sp_link_type(link) != SP_LINKTYPE_TRACK) {\n\t\tfprintf(stderr, \"Not a track link\\n\");\n\t\tsp_link_release(link);\n\t\treturn -1;\n\t}\n\n\ttrack = sp_link_as_track(link);\n\tsp_track_set_starred(g_session, &track, 1, set);\n\tsp_link_release(link);\n\treturn -1;\n}\n\n\n/**\n *\n */\nint cmd_star(int argc, char **argv)\n{\n\treturn dostar(argc, argv, 1);\n}\n\n\n/**\n *\n */\nint cmd_unstar(int argc, char **argv)\n{\n\treturn dostar(argc, argv, 0);\n}\n\n/**\n *\n */\nint cmd_starred(int argc, char **argv)\n{\n\tsp_playlist *starred;\n\tif (argc > 1) {\n\t\tstarred = sp_session_starred_for_user_create(g_session, argv[1]);\n\t} else {\n\t\tstarred = sp_session_starred_create(g_session);\n\t}\n\tif (starred) {\n\t\tbrowse_playlist(starred);\n\t} else {\n\t\tprintf(\"Starred not loaded\\n\");\n\t}\n\t\n\treturn 1;\n}\n"
  },
  {
    "path": "libspotify/examples/spshell/test.c",
    "content": "/**\n * Copyright (c) 2006-2011 Spotify Ltd\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n *\n */\n#include <stdarg.h>\n#include <stdio.h>\n#include <string.h>\n\n#if __APPLE__ || __linux__\n#include <sys/resource.h>\n#endif // __APPLE__ || __linux__\n\n#include \"spshell.h\"\n#include \"cmd.h\"\n\n#define STRINGIFY(s) TOSTRING(s)\n#define TOSTRING(s) #s\n\n\n\nenum msglevel {\n\tMSG_ERROR,\n\tMSG_INFO,\n\tMSG_OK,\n};\n\n#if WIN32\nconst char *dec_by_level[] = {\n\t\"\",\n\t\"\",\n\t\"\"\n};\nstatic const char *decorate_clr = \"\";\n#else\nconst char *dec_by_level[] = {\n\t\"\\033[31m\",\n\t\"\\033[36m\",\n\t\"\\033[32m\"\n};\nstatic const char *decorate_clr   = \"\\033[0m\";\n#endif\n\ntypedef struct Test {\n\t// Initialized by TEST_DECL\n\tconst char *title;\n\tint maxtime;\n\tint arg1;\n\tint arg2;\n\tint arg3;\n\n\t// Other members\n\tstruct Test *next;\n\tsp_uint64 start;\n\tint duration;\n\tint done;\n} Test;\n\nstatic struct Test *active_tests;\n\n\n\n\n#define TEST_DECL(title,maxtime) Test title = { STRINGIFY(title), maxtime }\n#define TEST_DECL3(title,maxtime, a) Test title = { STRINGIFY(title), maxtime, a }\n#define TEST_DECL4(title,maxtime, a,b) Test title = { STRINGIFY(title), maxtime, a,b }\n#define TEST_DECL5(title,maxtime, a,b,c) Test title = { STRINGIFY(title), maxtime, a,b,c }\n\nvoid test_activate(struct Test *t)\n{\n\tt->next = active_tests;\n\tactive_tests = t;\n}\n\n\nvoid test_list_active(void)\n{\n\tstruct Test *t;\n\tfor(t = active_tests; t != NULL; t = t->next)\n\t\tprintf(\"%s\\n\", t->title);\n}\n\n\nvoid output(enum msglevel level, const char *fmt, ...)\n{\n\tchar msg[512];\n\tva_list ap;\n\n\tva_start(ap, fmt);\n\tvsnprintf(msg, sizeof(msg), fmt, ap);\n\tva_end(ap);\n\n\tprintf(\"%s%s%s\\n\", dec_by_level[level], msg, decorate_clr);\n\n}\n\nvoid test_deactivate(const struct Test * const t)\n{\n\tstruct Test *l, **p = &active_tests;\n\n\twhile((l = *p) != NULL) {\n\t\tif(t == l) {\n\t\t\t*p = l->next;\n\t\t\treturn;\n\t\t}\n\t\tp = &l->next;\n\t}\n\toutput(MSG_ERROR, \"Test %s not linked\", t->title);\n\tabort();\n}\n\n\nstatic int test_done(Test *t, int backend_time)\n{\n\tt->done++;\n\n\tif(t->done > 1) {\n\t\toutput(MSG_ERROR, \"%s: Finished multiple times (%d)\", t->title, t->done);\n\t\tabort();\n\t\treturn 1;\n\t}\n\n\ttest_deactivate(t);\n\n\tt->duration = (int)(get_ts() - t->start);\n\n\tif(t->duration > t->maxtime * 1000) {\n\t\tchar trailer[100];\n\n\t\tif(backend_time != -1) {\n\t\t\tsnprintf(trailer, sizeof(trailer), \", %dms waiting for backend\",\n\t\t\t\t backend_time);\n\t\t} else {\n\t\t\ttrailer[0] = 0;\n\t\t}\n\t\toutput(MSG_ERROR, \"%s: %d Time exceeded, limit is %dms%s\",\n\t\t       t->title, t->duration, t->maxtime * 1000, trailer);\n\t\treturn 1;\n\t}\n\treturn 0;\n}\n\n\nstatic void test_ok(Test *t)\n{\n\tif(test_done(t, -1))\n\t\treturn;\n\n\toutput(MSG_OK, \"%s: %d OK\", t->title, t->duration);\n}\n\n\nstatic void test_ok_backend_duration(Test *t, int backend_duration)\n{\n\tchar trailer[100];\n\n\tif(test_done(t, backend_duration))\n\t\treturn;\n\n\tif(backend_duration == -1)\n\t\tstrcpy(trailer, \"Loaded from cache\");\n\telse\n\t\tsnprintf(trailer, sizeof(trailer), \"%d ms backend request delay\", backend_duration);\n\n\toutput(MSG_OK, \"%s: %d OK, %s\", t->title, t->duration, trailer);\n}\n\nstatic void test_report(Test *t, const char *fmt, ...)\n{\n\tchar msg[512];\n\tva_list ap;\n\tint level;\n\n\tif(test_done(t, -1))\n\t\treturn;\n\n\tlevel = MSG_ERROR;\n\tva_start(ap, fmt);\n\tvsnprintf(msg, sizeof(msg), fmt, ap);\n\tva_end(ap);\n\n\toutput(level, \"%s: %d %s\", t->title, t->duration, msg);\n}\n\n\n#define info_report(fmt, ...) output(MSG_INFO, fmt, ##__VA_ARGS__)\n\n\nstatic void test_start(Test *t)\n{\n\tt->start = get_ts();\n\ttest_activate(t);\n}\n\n/*****************************************************************\n * URI helpers\n */\nstatic sp_artist *artist_from_uri(const char *uri)\n{\n\tsp_artist *a;\n\tsp_link *l = sp_link_create_from_string(uri);\n\tif(sp_link_type(l) != SP_LINKTYPE_ARTIST) {\n\t\tsp_link_release(l);\n\t\treturn NULL;\n\t}\n\ta = sp_link_as_artist(l);\n\tsp_artist_add_ref(a);\n\tsp_link_release(l);\n\treturn a;\n}\n\n\nstatic sp_album *album_from_uri(const char *uri)\n{\n\tsp_album *a;\n\tsp_link *l = sp_link_create_from_string(uri);\n\tif(sp_link_type(l) != SP_LINKTYPE_ALBUM) {\n\t\tsp_link_release(l);\n\t\treturn NULL;\n\t}\n\ta = sp_link_as_album(l);\n\tsp_album_add_ref(a);\n\tsp_link_release(l);\n\treturn a;\n}\n\n\nstatic sp_track *track_from_uri(const char *uri)\n{\n\tsp_track *t;\n\tsp_link *l = sp_link_create_from_string(uri);\n\tif(sp_link_type(l) != SP_LINKTYPE_TRACK) {\n\t\tsp_link_release(l);\n\t\treturn NULL;\n\t}\n\tt = sp_link_as_track(l);\n\tsp_track_add_ref(t);\n\tsp_link_release(l);\n\treturn t;\n}\n\n\n/*****************************************************************\n * Search\n */\nTEST_DECL(search1, 3);\nTEST_DECL(search2, 3);\nTEST_DECL(did_you_mean, 3);\n\n\nstatic void SP_CALLCONV search1_cb(sp_search *result, void *userdata)\n{\n\tif(!sp_search_is_loaded(result))\n\t\ttest_report(userdata, \"Result not loaded\");\n\telse if(sp_search_error(result) != SP_ERROR_OK)\n\t\ttest_report(userdata, \"%s\", sp_error_message(sp_search_error(result)));\n\telse if(sp_search_num_tracks(result) != 2)\n\t\ttest_report(userdata, \"Expected %d tracks got %d\", 2, sp_search_num_tracks(result));\n\telse if(sp_search_total_tracks(result) < sp_search_num_tracks(result))\n\t\ttest_report(userdata, \"Total tracks (%d) less than number of tracks (%d)\", sp_search_total_tracks(result), sp_search_num_tracks(result));\n\telse if(sp_search_num_albums(result) != 4)\n\t\ttest_report(userdata, \"Expected %d albums got %d\", 4, sp_search_num_albums(result));\n\telse if(sp_search_total_albums(result) < sp_search_num_albums(result))\n\t\ttest_report(userdata, \"Total albums (%d) less than number of albums (%d)\", sp_search_total_albums(result), sp_search_num_albums(result));\n\telse if(sp_search_num_artists(result) != 6)\n\t\ttest_report(userdata, \"Expected %d artists got %d\", 6, sp_search_num_artists(result));\n\telse if(sp_search_total_artists(result) < sp_search_num_artists(result))\n\t\ttest_report(userdata, \"Total artists (%d) less than number of artists (%d)\", sp_search_total_artists(result), sp_search_num_artists(result));\n\telse if(sp_search_num_playlists(result) != 8)\n\t\ttest_report(userdata, \"Expected %d playlists got %d\", 8, sp_search_num_playlists(result));\n\telse if(sp_search_total_playlists(result) < sp_search_num_playlists(result))\n\t\ttest_report(userdata, \"Total playlists (%d) less than number of playlists (%d)\", sp_search_total_playlists(result), sp_search_num_playlists(result));\n\telse {\n\t\tif (!sp_search_playlist_name(result, 1)) {\n\t\t\ttest_report(userdata, \"Expected a name for playlist #1\");\n\t\t} else\n\t\t\ttest_ok(userdata);\n\t}\n\tsp_search_release(result);\n}\n\n\nstatic void SP_CALLCONV search2_cb(sp_search *result, void *userdata)\n{\n\tif(!sp_search_is_loaded(result))\n\t\ttest_report(userdata, \"Result not loaded\");\n\telse if(sp_search_error(result) != SP_ERROR_OK)\n\t\ttest_report(userdata, \"%s\", sp_error_message(sp_search_error(result)));\n\telse\n\t\ttest_ok(userdata);\n\tsp_search_release(result);\n}\n\nstatic void SP_CALLCONV did_you_mean_cb(sp_search *result, void *userdata)\n{\n\tif(!sp_search_is_loaded(result))\n\t\ttest_report(userdata, \"Result not loaded\");\n\telse if(sp_search_error(result) != SP_ERROR_OK)\n\t\ttest_report(userdata, \"%s\", sp_error_message(sp_search_error(result)));\n\telse if(strcmp(sp_search_did_you_mean(result), \"madonna\"))\n\t\ttest_report(userdata, \"Expected '%s' but got '%s'\",\n\t\t\t    \"madonna\", sp_search_did_you_mean(result));\n\telse\n\t\ttest_ok(userdata);\n\tsp_search_release(result);\n}\n\n\nstatic void search_test(void)\n{\n\ttest_start(&search1);\n\tsp_search_create(g_session, \"madonna\", 1,2,3,4,5,6,7,8, SP_SEARCH_STANDARD, search1_cb, &search1);\n\n\ttest_start(&search2);\n\tsp_search_create(g_session, \"madonna\", 0,250,0,250,0,250, 0, 0, SP_SEARCH_STANDARD, search2_cb, &search2);\n\n\ttest_start(&did_you_mean);\n\tsp_search_create(g_session, \"madonnnna\", 0,250,0,250,0,250, 0, 0, SP_SEARCH_STANDARD, did_you_mean_cb, &did_you_mean);\n}\n\n\n/*****************************************************************\n * Album browse\n */\nTEST_DECL(browse_50th_law, 3);\n\nstatic void SP_CALLCONV album_cb(sp_albumbrowse *result, void *userdata)\n{\n\tif(!sp_albumbrowse_is_loaded(result))\n\t\ttest_report(userdata, \"Result not loaded\");\n\telse if(sp_albumbrowse_error(result) != SP_ERROR_OK)\n\t\ttest_report(userdata, \"%s\", sp_error_message(sp_albumbrowse_error(result)));\n\telse if(sp_albumbrowse_num_tracks(result) != 11)\n\t\ttest_report(userdata, \"Expected 11 tracks but got %d\", sp_albumbrowse_num_tracks(result));\n\telse if(strcmp(\"Introduction - Excerpt\",\n\t\t       sp_track_name(sp_albumbrowse_track(result, 0))))\n\t\ttest_report(userdata, \"Expected track #1 to be %s but got %s\",\n\t\t\t    \"Introduction - Excerpt\",\n\t\t\t    sp_track_name(sp_albumbrowse_track(result, 0)));\n\telse if(strcmp(\"Confront Your Mortality – the Sublime - Excerpt\",\n\t\t       sp_track_name(sp_albumbrowse_track(result, 10))))\n\t\ttest_report(userdata, \"Expected track #11 to be %s but got %s\",\n\t\t\t    \"Confront Your Mortality – the Sublime - Excerpt\",\n\t\t\t    sp_track_name(sp_albumbrowse_track(result, 10)));\n\telse\n\t\ttest_ok_backend_duration(userdata, sp_albumbrowse_backend_request_duration(result));\n\tsp_albumbrowse_release(result);\n}\n\n\n\nstatic void albumbrowse_test(void)\n{\n\tsp_album *alb;\n\ttest_start(&browse_50th_law);\n\n\talb = album_from_uri(\"spotify:album:1kSXIcMv2voPwcjaJiUoC5\");\n\tsp_albumbrowse_create(g_session, alb, album_cb, &browse_50th_law);\n\tsp_album_release(alb);\n}\n\n\n/*****************************************************************\n * Artist browse no albums\n */\nTEST_DECL(browse_david_guetta, 3);\nTEST_DECL(browse_adele, 3);\nTEST_DECL(browse_veronica_maggio, 3);\nTEST_DECL(browse_rihanna, 3);\nTEST_DECL(browse_elvis, 3);\n\n\nstatic void SP_CALLCONV no_albums_cb(sp_artistbrowse *result, void *userdata)\n{\n\tif(!sp_artistbrowse_is_loaded(result))\n\t\ttest_report(userdata, \"Result not loaded\");\n\telse if(sp_artistbrowse_error(result) != SP_ERROR_OK)\n\t\ttest_report(userdata, \"%s\", sp_error_message(sp_artistbrowse_error(result)));\n\telse if(sp_artistbrowse_num_tracks(result))\n\t\ttest_report(userdata, \"Expected 0 tracks but got %d\", sp_artistbrowse_num_tracks(result));\n\telse if(sp_artistbrowse_num_albums(result))\n\t\ttest_report(userdata, \"Expected 0 albums but got %d\", sp_artistbrowse_num_albums(result));\n\telse\n\t\ttest_ok_backend_duration(userdata, sp_artistbrowse_backend_request_duration(result));\n\tsp_artistbrowse_release(result);\n}\n\n\n\nstatic void artistbrowse_test(void)\n{\n\tsp_artist *art;\n\ttest_start(&browse_david_guetta);\n\ttest_start(&browse_adele);\n\ttest_start(&browse_veronica_maggio);\n\ttest_start(&browse_rihanna);\n\ttest_start(&browse_elvis);\n\n\tart = artist_from_uri(\"spotify:artist:1Cs0zKBU1kc0i8ypK3B9ai\");\n\tsp_artistbrowse_create(g_session, art, SP_ARTISTBROWSE_NO_ALBUMS, no_albums_cb, &browse_david_guetta);\n\tsp_artist_release(art);\n\n\tart = artist_from_uri(\"spotify:artist:4dpARuHxo51G3z768sgnrY\");\n\tsp_artistbrowse_create(g_session, art, SP_ARTISTBROWSE_NO_ALBUMS, no_albums_cb, &browse_adele);\n\tsp_artist_release(art);\n\n\tart = artist_from_uri(\"spotify:artist:2OIWxN9xUhgUHkeUCWCaNs\");\n\tsp_artistbrowse_create(g_session, art, SP_ARTISTBROWSE_NO_ALBUMS, no_albums_cb, &browse_veronica_maggio);\n\tsp_artist_release(art);\n\n\tart = artist_from_uri(\"spotify:artist:5pKCCKE2ajJHZ9KAiaK11H\");\n\tsp_artistbrowse_create(g_session, art, SP_ARTISTBROWSE_NO_ALBUMS, no_albums_cb, &browse_rihanna);\n\tsp_artist_release(art);\n\n\tart = artist_from_uri(\"spotify:artist:43ZHCT0cAZBISjO8DG9PnE\");\n\tsp_artistbrowse_create(g_session, art, SP_ARTISTBROWSE_NO_ALBUMS, no_albums_cb, &browse_elvis);\n\tsp_artist_release(art);\n}\n\n\n/*****************************************************************\n * Artist browse no tracks\n */\nTEST_DECL(browse_no_tracks_elvis, 10);\n\n\nstatic void SP_CALLCONV no_tracks_cb(sp_artistbrowse *result, void *userdata)\n{\n\tif(!sp_artistbrowse_is_loaded(result))\n\t\ttest_report(userdata, \"Result not loaded\");\n\telse if(sp_artistbrowse_error(result) != SP_ERROR_OK)\n\t\ttest_report(userdata, \"%s\", sp_error_message(sp_artistbrowse_error(result)));\n\telse if(sp_artistbrowse_num_tracks(result))\n\t\ttest_report(userdata, \"Expected 0 tracks but got %d\", sp_artistbrowse_num_tracks(result));\n\telse\n\t\ttest_ok_backend_duration(userdata, sp_artistbrowse_backend_request_duration(result));\n\tsp_artistbrowse_release(result);\n}\n\n\n\nstatic void artistbrowse_no_tracks_test(void)\n{\n\tsp_artist *art;\n\ttest_start(&browse_no_tracks_elvis);\n\n\tart = artist_from_uri(\"spotify:artist:43ZHCT0cAZBISjO8DG9PnE\");\n\tsp_artistbrowse_create(g_session, art, SP_ARTISTBROWSE_NO_TRACKS, no_tracks_cb, &browse_no_tracks_elvis);\n\tsp_artist_release(art);\n}\n\n\n\n/*****************************************************************\n * Toplist browse\n */\nTEST_DECL5(browse_toplist_artist_global, 3,  0,   0,   100);\nTEST_DECL5(browse_toplist_album_global,  3,  0,   100, 0);\nTEST_DECL5(browse_toplist_track_global,  3,  100, 0,   0);\nTEST_DECL5(browse_toplist_artist_user,   3,  0,   0,   20);\nTEST_DECL5(browse_toplist_album_user,    3,  0,   20,  0);\nTEST_DECL5(browse_toplist_track_user,    3,  20,  0,   0);\nTEST_DECL5(browse_toplist_artist_SE,     3,  0,   0,   100);\nTEST_DECL5(browse_toplist_album_SE,      3,  0,   100, 0);\nTEST_DECL5(browse_toplist_track_SE,      3,  100, 0,   0);\nTEST_DECL5(browse_toplist_artist_US,     3,  0,   0,   100);\nTEST_DECL5(browse_toplist_album_US,      3,  0,   100, 0);\nTEST_DECL5(browse_toplist_track_US,      3,  100, 0,   0);\n\nstatic void SP_CALLCONV toplist_cb(sp_toplistbrowse *result, void *userdata)\n{\n\tconst Test *t = userdata;\n\tif(!sp_toplistbrowse_is_loaded(result))\n\t\ttest_report(userdata, \"Result not loaded\");\n\telse if(sp_toplistbrowse_error(result) != SP_ERROR_OK)\n\t\ttest_report(userdata, \"%s\", sp_error_message(sp_toplistbrowse_error(result)));\n\telse if(t->arg1 != sp_toplistbrowse_num_tracks(result))\n\t\ttest_report(userdata, \"Expected %d tracks but got %d\",\n\t\t\t    t->arg1, sp_toplistbrowse_num_tracks(result));\n\telse if(t->arg2 != sp_toplistbrowse_num_albums(result))\n\t\ttest_report(userdata, \"Expected %d albums but got %d\",\n\t\t\t    t->arg2, sp_toplistbrowse_num_albums(result));\n\telse if(t->arg3 != sp_toplistbrowse_num_artists(result))\n\t\ttest_report(userdata, \"Expected %d artists but got %d\",\n\t\t\t    t->arg3, sp_toplistbrowse_num_artists(result));\n\telse\n\t\ttest_ok_backend_duration(userdata, sp_toplistbrowse_backend_request_duration(result));\n\tsp_toplistbrowse_release(result);\n}\n\n\n\nstatic void toplistbrowse_test(void)\n{\n\ttest_start(&browse_toplist_artist_global);\n\ttest_start(&browse_toplist_album_global);\n\ttest_start(&browse_toplist_track_global);\n\n\ttest_start(&browse_toplist_artist_user);\n\ttest_start(&browse_toplist_album_user);\n\ttest_start(&browse_toplist_track_user);\n\n\ttest_start(&browse_toplist_artist_SE);\n\ttest_start(&browse_toplist_album_SE);\n\ttest_start(&browse_toplist_track_SE);\n\n\ttest_start(&browse_toplist_artist_US);\n\ttest_start(&browse_toplist_album_US);\n\ttest_start(&browse_toplist_track_US);\n\n\tsp_toplistbrowse_create(g_session, SP_TOPLIST_TYPE_ARTISTS,\n\t\t\t\tSP_TOPLIST_REGION_EVERYWHERE, NULL,\n\t\t\t\ttoplist_cb, &browse_toplist_artist_global);\n\n\tsp_toplistbrowse_create(g_session, SP_TOPLIST_TYPE_ALBUMS,\n\t\t\t\tSP_TOPLIST_REGION_EVERYWHERE, NULL,\n\t\t\t\ttoplist_cb, &browse_toplist_album_global);\n\n\tsp_toplistbrowse_create(g_session, SP_TOPLIST_TYPE_TRACKS,\n\t\t\t\tSP_TOPLIST_REGION_EVERYWHERE, NULL,\n\t\t\t\ttoplist_cb, &browse_toplist_track_global);\n\n\n\tsp_toplistbrowse_create(g_session, SP_TOPLIST_TYPE_ARTISTS,\n\t\t\t\tSP_TOPLIST_REGION_USER, NULL,\n\t\t\t\ttoplist_cb, &browse_toplist_artist_user);\n\n\tsp_toplistbrowse_create(g_session, SP_TOPLIST_TYPE_ALBUMS,\n\t\t\t\tSP_TOPLIST_REGION_USER, NULL,\n\t\t\t\ttoplist_cb, &browse_toplist_album_user);\n\n\tsp_toplistbrowse_create(g_session, SP_TOPLIST_TYPE_TRACKS,\n\t\t\t\tSP_TOPLIST_REGION_USER, NULL,\n\t\t\t\ttoplist_cb, &browse_toplist_track_user);\n\n\n\n\tsp_toplistbrowse_create(g_session, SP_TOPLIST_TYPE_ARTISTS,\n\t\t\t\tSP_TOPLIST_REGION('S', 'E'), NULL,\n\t\t\t\ttoplist_cb, &browse_toplist_artist_SE);\n\n\tsp_toplistbrowse_create(g_session, SP_TOPLIST_TYPE_ALBUMS,\n\t\t\t\tSP_TOPLIST_REGION('S', 'E'), NULL,\n\t\t\t\ttoplist_cb, &browse_toplist_album_SE);\n\n\tsp_toplistbrowse_create(g_session, SP_TOPLIST_TYPE_TRACKS,\n\t\t\t\tSP_TOPLIST_REGION('S', 'E'), NULL,\n\t\t\t\ttoplist_cb, &browse_toplist_track_SE);\n\n\n\tsp_toplistbrowse_create(g_session, SP_TOPLIST_TYPE_ARTISTS,\n\t\t\t\tSP_TOPLIST_REGION('U', 'S'), NULL,\n\t\t\t\ttoplist_cb, &browse_toplist_artist_US);\n\n\tsp_toplistbrowse_create(g_session, SP_TOPLIST_TYPE_ALBUMS,\n\t\t\t\tSP_TOPLIST_REGION('U', 'S'), NULL,\n\t\t\t\ttoplist_cb, &browse_toplist_album_US);\n\n\tsp_toplistbrowse_create(g_session, SP_TOPLIST_TYPE_TRACKS,\n\t\t\t\tSP_TOPLIST_REGION('U', 'S'), NULL,\n\t\t\t\ttoplist_cb, &browse_toplist_track_US);\n}\n\n/*****************************************************************\n * Radio\n */\n#ifdef SP_WITH_RADIO\n\nTEST_DECL(radio_artist,3);\nTEST_DECL(radio_track,3);\nTEST_DECL(radio_genre,3);\n\n\nstatic void radio_cb(sp_radio *result, void *userdata)\n{\n\tint num_tracks;\n\tsp_track* track;\n\n\tif(!sp_radio_is_loaded(result))\n\t\ttest_report(userdata, \"Result not loaded\");\n\telse if(sp_radio_error(result) != SP_ERROR_OK)\n\t\ttest_report(userdata, \"%s\", sp_error_message(sp_radio_error(result)));\n\telse {\n\t\tnum_tracks=sp_radio_num_tracks(result);\n\t\tif (num_tracks>0) {\n\t\t\ttrack = sp_radio_track(result, num_tracks - 1);\n\t\t\tif ( track ) {\n\t\t\t\ttest_ok(userdata);\n\t\t\t} else {\n\t\t\t\ttest_report(userdata, \"Can't get last track\");\n\t\t\t}\n\t\t} else {\n\t\t\ttest_report(userdata, \"No tracks returned\");\n\t\t}\n\t}\n\tsp_radio_release(result);\n}\n\nstatic void radio_test(void)\n{\n\tsp_link* link;\n\ttest_start(&radio_artist);\n\tlink = sp_link_create_from_string(\"spotify:artist:6tbjWDEIzxoDsBA1FuhfPW\"); // Madonna\n\tsp_radio_create_from_link(g_session, link, &radio_cb, &radio_artist);\n\tsp_link_release( link );\n\n\ttest_start(&radio_track);\n\tlink = sp_link_create_from_string(\"spotify:track:1z3ugFmUKoCzGsI6jdY4Ci\"); // Like A Prayer\n\tsp_radio_create_from_link(g_session, link, &radio_cb, &radio_track);\n\tsp_link_release( link );\n\n\ttest_start(&radio_genre);\n\tsp_radio_create_from_genre(g_session, SP_RADIO_GENRE_DANCE, &radio_cb, &radio_genre);\n}\n\n#endif\n/*****************************************************************\n * Streaming test\n */\n\nTEST_DECL(playtrack, 25);\n\nstatic sp_track *stream_track;\nstatic int stream_track_end;\n\n\n/**\n * Callback from spotify session. Happen on different thread so we need to signal and wakeup\n */\nvoid SP_CALLCONV end_of_track(sp_session *s)\n{\n\tstream_track_end = 1;\n\tnotify_main_thread(g_session);\n\tinfo_report(\"end of track\");\n}\n\n/**\n * Callback from spotify session. Just consume all frames\n */\nint SP_CALLCONV music_delivery(sp_session *s, const sp_audioformat *fmt, const void *frames, int num_frames)\n{\n\treturn num_frames;\n}\n\n/**\n * Callback from spotify session. Happen on different thread so we need to signal and wakeup\n */\nvoid SP_CALLCONV play_token_lost(sp_session *s)\n{\n\tstream_track_end = 2;\n\tnotify_main_thread(g_session);\n\tinfo_report(\"Playtoken lost\");\n}\n\n\nstatic void playtrack_test(void)\n{\n\tsp_error err;\n\ttest_start(&playtrack);\n\tif((err = sp_session_player_load(g_session, stream_track)) != SP_ERROR_OK) {\n\t\ttest_report(&playtrack, \"Unable to load track: %s\",  sp_error_message(err));\n\t\treturn;\n\t}\n\tinfo_report(\"Streaming '%s' by '%s' this will take a while\", sp_track_name(stream_track),\n\t\t    sp_artist_name(sp_track_artist(stream_track, 0)));\n\tsp_session_player_play(g_session, 1);\n}\n\nstatic int check_streaming_done(void)\n{\n\tif(stream_track_end == 2)\n\t\ttest_report(&playtrack, \"Playtoken lost\");\n\telse if(stream_track_end == 1)\n\t\ttest_ok(&playtrack);\n\telse\n\t\treturn 0;\n\tstream_track_end = 0;\n\treturn 1;\n}\n\n/*****************************************************************\n * Image loading\n */\nTEST_DECL3(image1, 3, 4560901);\nTEST_DECL3(image2, 3, 4920563);\nTEST_DECL3(image3, 3, 4440836);\nTEST_DECL3(image4, 3, 2202765);\nTEST_DECL3(image5, 3, 3254083);\nTEST_DECL3(image6, 3, 2595372);\nTEST_DECL3(image7, 3, 10028876);\nTEST_DECL3(image8, 3, 7017370);\nTEST_DECL3(image9, 3, 3655831);\n\nstatic void SP_CALLCONV image_cb(sp_image *image, void *userdata)\n{\n\tTest *t = userdata;\n\tsize_t size;\n\tconst byte *data;\n\tint sum;\n\tsize_t i;\n\n\tdata = sp_image_data(image, &size);\n\tsum = size;\n\tfor(i = 0; i < size; i++)\n\t\tsum += data[i];\n\n\tsp_image_release(image);\n\tif(sum != t->arg1)\n\t\ttest_report(userdata, \"Invalid checksum\");\n\telse\n\t\ttest_ok(userdata);\n}\n\n\nstatic void load_image(Test *t, const char *uri)\n{\n\tsp_link *l;\n\tsp_image *img;\n\n\ttest_start(t);\n\n\tl = sp_link_create_from_string(uri);\n\timg = sp_image_create_from_link(g_session, l);\n\tsp_image_add_load_callback(img, image_cb, t);\n\tsp_link_release(l);\n\n}\n\nstatic void image_test(void)\n{\n\tload_image(&image1, \"spotify:image:34062b6f0168af33b9cd80c630a38f5de183f936\");\n\tload_image(&image2, \"spotify:image:654873a4d6a648f24055a5faec324aa2a80a997d\");\n\tload_image(&image3, \"spotify:image:5a9b36ac716b1178dc35bd05db96a34eafb77ad4\");\n\tload_image(&image4, \"spotify:image:564ce92718a792307f40634cb3225f0e91d7965b\");\n\tload_image(&image5, \"spotify:image:67b169a8a8df439437df7424ccd5dd7b7d88fca8\");\n\tload_image(&image6, \"spotify:image:b05e1aaf5824c9e4736b5d7b173aec5fdd4e6a4e\");\n\tload_image(&image7, \"spotify:image:0f44e39b1e7c21701640bb5ad035efde02b6aeeb\");\n\tload_image(&image8, \"spotify:image:c588570590c7d76670efad294424b991ddde17a0\");\n\tload_image(&image9, \"spotify:image:53a580c6e3e314838dcbc2ed97ebebb54a25693e\");\n}\n\n\n\n\n/*********************************************************************************\n * State machine\n */\n#define WAIT_FOR_TEST(t) state = __LINE__; case __LINE__: if(!(t)->done) return\n#define WAIT_FOR(expr)   state = __LINE__; case __LINE__: if(!(expr)) return\n\nstatic void print_resource_usage()\n{\n#if __APPLE__ || __linux__\n\tstruct rusage r_usage;\n\tint res;\n\n\tres = getrusage(RUSAGE_SELF, &r_usage);\n\tif (res == 0) {\n\t\tprintf(\"getrusage() returned:\\n\");\n\n#if __APPLE__\n#define TV_USEC_FORMAT \"d\"\n#elif __linux__\n#define TV_USEC_FORMAT \"ld\"\n#endif\n\t\tprintf(\"  User time:   %ld.%03\" TV_USEC_FORMAT \"s\\n\", r_usage.ru_utime.tv_sec, r_usage.ru_utime.tv_usec / 1000);\n\t\tprintf(\"  System time: %ld.%03\" TV_USEC_FORMAT \"s\\n\", r_usage.ru_stime.tv_sec, r_usage.ru_stime.tv_usec / 1000);\n#undef TV_USEC_FORMAT\n\n#if __APPLE__\n#define MAXRSS_UNITS \"bytes\"\n#elif __linux__\n#define MAXRSS_UNITS \"kilobytes\"\n#endif\n\t\tprintf(\"  Peak memory usage: %ld \" MAXRSS_UNITS \" (ru_maxrss)\\n\", r_usage.ru_maxrss); // integral max resident set size\n#undef MAXRSS_UNITS\n\n\t} else {\n\t\tperror(\"getrusage() failed\");\n\t}\n#endif // __APPLE__ || __linux__\n}\n\n/**\n *\n */\nvoid test_process(void)\n{\n\tstatic int state;\n\tswitch(state) {\n\tcase 0:\n\t\tsearch_test();\n\t\tWAIT_FOR(!active_tests);\n\n\t\talbumbrowse_test();\n\t\tWAIT_FOR(!active_tests);\n\n\t\tartistbrowse_test();\n\t\tWAIT_FOR(!active_tests);\n\n\t\tartistbrowse_no_tracks_test();\n\t\tWAIT_FOR(!active_tests);\n\n\t\timage_test();\n\t\tWAIT_FOR(!active_tests);\n\n\t\ttoplistbrowse_test();\n\t\tWAIT_FOR(!active_tests);\n\n#ifdef SP_WITH_RADIO\n\t\tradio_test();\n\t\tWAIT_FOR(!active_tests);\n#endif\n\n\t\tinfo_report(\"Loading %s\", \"spotify:track:5iIeIeH3LBSMK92cMIXrVD\");\n\t\tstream_track = track_from_uri(\"spotify:track:5iIeIeH3LBSMK92cMIXrVD\");\n\t\tWAIT_FOR(sp_track_is_loaded(stream_track));\n\n\t\tplaytrack_test();\n\n\t\tWAIT_FOR(check_streaming_done());\n\t\tWAIT_FOR(!active_tests);\n\t\tsp_track_release(stream_track);\n\n\t\tstate = -1;\n\t\ttest_finished();\n\t\tprint_resource_usage();\n\t}\n}\n\n\nint cmd_test(int argc, char **argv)\n{\n\textern int g_selftest;\n\tg_selftest = 1;\n\ttest_process();\n\treturn -1;\n}\n"
  },
  {
    "path": "libspotify/examples/spshell/toplist.c",
    "content": "/**\n * Copyright (c) 2006-2010 Spotify Ltd\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n *\n */\n\n#include <string.h>\n\n#include \"spshell.h\"\n#include \"cmd.h\"\n\n/**\n *\n */\nstatic void print_album(int index, sp_album *album)\n{\n\tprintf(\"  Album %3d: \\\"%s\\\" by \\\"%s\\\"\\n\", index, sp_album_name(album), \n\t       sp_artist_name(sp_album_artist(album)));\n}\n\n/**\n *\n */\nstatic void print_artist(int index, sp_artist *artist)\n{\n\tsp_link *l;\n\tchar url[200];\n\tprintf(\"  Artist %3d: \\\"%s\\\"\\n\", index, sp_artist_name(artist));\n\n\tl = sp_link_create_from_artist_portrait(artist, SP_IMAGE_SIZE_NORMAL);\n\tif(l != NULL) {\n\t\tsp_link_as_string(l, url, sizeof(url));\n\t\tprintf(\"    Portrait: %s\\n\", url);\n\t\tsp_link_release(l);\n\t}\n}\n\n\n/**\n * Callback for libspotify\n *\n * @param result    The toplist result object that is now done\n * @param userdata  The opaque pointer given to sp_toplistbrowse_create()\n */\nstatic void SP_CALLCONV got_toplist(sp_toplistbrowse *result, void *userdata)\n{\n\tint i;\n\n\t// We print from all types. Only one of the loops will acually yield anything.\n\n\tfor(i = 0; i < sp_toplistbrowse_num_artists(result); i++)\n\t\tprint_artist(i + 1, sp_toplistbrowse_artist(result, i));\n\n\tfor(i = 0; i < sp_toplistbrowse_num_albums(result); i++)\n\t\tprint_album(i + 1, sp_toplistbrowse_album(result, i));\n\n\tfor(i = 0; i < sp_toplistbrowse_num_tracks(result); i++) {\n\t\tprintf(\"%3d: \", i + 1);\n\t\tprint_track(sp_toplistbrowse_track(result, i));\n\t}\n\n\tsp_toplistbrowse_release(result);\n\tcmd_done();\n}\n\n\n\n/**\n *\n */\nstatic void toplist_usage(void)\n{\n\tfprintf(stderr, \"Usage: toplist (tracks | albums | artists) (global | region <countrycode> | user)\\n\");\n}\n\n/**\n *\n */\nint cmd_toplist(int argc, char **argv)\n{\n\tsp_toplisttype type;\n\tsp_toplistregion region;\n\n\tif(argc < 3) {\n\t\ttoplist_usage();\n\t\treturn -1;\n\t}\n\n\tif(!strcasecmp(argv[1], \"artists\"))\n\t\ttype = SP_TOPLIST_TYPE_ARTISTS;\n\telse if(!strcasecmp(argv[1], \"albums\"))\n\t\ttype = SP_TOPLIST_TYPE_ALBUMS;\n\telse if(!strcasecmp(argv[1], \"tracks\"))\n\t\ttype = SP_TOPLIST_TYPE_TRACKS;\n\telse {\n\t\ttoplist_usage();\n\t\treturn -1;\n\t}\n\n\n\tif(!strcasecmp(argv[2], \"global\"))\n\t\tregion = SP_TOPLIST_REGION_EVERYWHERE;\n\telse if(!strcasecmp(argv[2], \"user\"))\n\t\tregion = SP_TOPLIST_REGION_USER;\n\telse if(!strcasecmp(argv[2], \"region\")) {\n\n\t\tif(argc != 4 || strlen(argv[3]) != 2) {\n\t\t\ttoplist_usage();\n\t\t\treturn -1;\n\t\t}\n\t\tregion = SP_TOPLIST_REGION(argv[3][0], argv[3][1]);\n\t} else {\n\t\ttoplist_usage();\n\t\treturn -1;\n\t}\n\n\tsp_toplistbrowse_create(g_session, type, region, NULL, got_toplist, NULL);\n\treturn 0;\n}\n"
  },
  {
    "path": "libspotify/examples/spshell/win32/spshell.vcproj",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<VisualStudioProject\n\tProjectType=\"Visual C++\"\n\tVersion=\"9,00\"\n\tName=\"spshell\"\n\tProjectGUID=\"{6C49596C-977E-4BB6-BC94-123AEB5E2724}\"\n\tKeyword=\"Win32Proj\"\n\tTargetFrameworkVersion=\"131072\"\n\t>\n\t<Platforms>\n\t\t<Platform\n\t\t\tName=\"Win32\"\n\t\t/>\n\t</Platforms>\n\t<ToolFiles>\n\t</ToolFiles>\n\t<Configurations>\n\t\t<Configuration\n\t\t\tName=\"Debug|Win32\"\n\t\t\tOutputDirectory=\"Debug\"\n\t\t\tIntermediateDirectory=\"Debug\"\n\t\t\tConfigurationType=\"1\"\n\t\t\t>\n\t\t\t<Tool\n\t\t\t\tName=\"VCPreBuildEventTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCCustomBuildTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCXMLDataGeneratorTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCWebServiceProxyGeneratorTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCMIDLTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\tOptimization=\"0\"\n\t\t\t\tAdditionalIncludeDirectories=\"&quot;$(LIBSPOTIFY)\\include&quot;;..\\..\\..\\include\"\n\t\t\t\tPreprocessorDefinitions=\"WIN32;_DEBUG;_CONSOLE;\"\n\t\t\t\tMinimalRebuild=\"true\"\n\t\t\t\tBasicRuntimeChecks=\"3\"\n\t\t\t\tRuntimeLibrary=\"3\"\n\t\t\t\tUsePrecompiledHeader=\"0\"\n\t\t\t\tWarningLevel=\"3\"\n\t\t\t\tDetect64BitPortabilityProblems=\"false\"\n\t\t\t\tDebugInformationFormat=\"3\"\n\t\t\t\tCallingConvention=\"2\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCManagedResourceCompilerTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCResourceCompilerTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCPreLinkEventTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCLinkerTool\"\n\t\t\t\tAdditionalDependencies=\"libspotify.lib\"\n\t\t\t\tLinkIncremental=\"2\"\n\t\t\t\tAdditionalLibraryDirectories=\"&quot;$(LIBSPOTIFY)\\lib&quot;;..\\..\\..\\lib\"\n\t\t\t\tGenerateDebugInformation=\"true\"\n\t\t\t\tSubSystem=\"1\"\n\t\t\t\tRandomizedBaseAddress=\"1\"\n\t\t\t\tDataExecutionPrevention=\"0\"\n\t\t\t\tTargetMachine=\"1\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCALinkTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCManifestTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCXDCMakeTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCBscMakeTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCFxCopTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCAppVerifierTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCPostBuildEventTool\"\n\t\t\t/>\n\t\t</Configuration>\n\t\t<Configuration\n\t\t\tName=\"Release|Win32\"\n\t\t\tOutputDirectory=\"Release\"\n\t\t\tIntermediateDirectory=\"Release\"\n\t\t\tConfigurationType=\"1\"\n\t\t\t>\n\t\t\t<Tool\n\t\t\t\tName=\"VCPreBuildEventTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCCustomBuildTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCXMLDataGeneratorTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCWebServiceProxyGeneratorTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCMIDLTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\tAdditionalIncludeDirectories=\"$(LIBSPOTIFY)\\include;..\\..\\..\\include\"\n\t\t\t\tPreprocessorDefinitions=\"WIN32;NDEBUG;_CONSOLE;\"\n\t\t\t\tRuntimeLibrary=\"2\"\n\t\t\t\tUsePrecompiledHeader=\"0\"\n\t\t\t\tWarningLevel=\"3\"\n\t\t\t\tDetect64BitPortabilityProblems=\"true\"\n\t\t\t\tDebugInformationFormat=\"3\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCManagedResourceCompilerTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCResourceCompilerTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCPreLinkEventTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCLinkerTool\"\n\t\t\t\tAdditionalDependencies=\"libspotify.lib\"\n\t\t\t\tLinkIncremental=\"1\"\n\t\t\t\tAdditionalLibraryDirectories=\"$(LIBSPOTIFY)\\lib;;..\\..\\..\\lib\"\n\t\t\t\tGenerateDebugInformation=\"true\"\n\t\t\t\tSubSystem=\"1\"\n\t\t\t\tOptimizeReferences=\"2\"\n\t\t\t\tEnableCOMDATFolding=\"2\"\n\t\t\t\tRandomizedBaseAddress=\"1\"\n\t\t\t\tDataExecutionPrevention=\"0\"\n\t\t\t\tTargetMachine=\"1\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCALinkTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCManifestTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCXDCMakeTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCBscMakeTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCFxCopTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCAppVerifierTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCPostBuildEventTool\"\n\t\t\t/>\n\t\t</Configuration>\n\t</Configurations>\n\t<References>\n\t</References>\n\t<Files>\n\t\t<Filter\n\t\t\tName=\"Header Files\"\n\t\t\tFilter=\"h;hpp;hxx;hm;inl;inc;xsd\"\n\t\t\tUniqueIdentifier=\"{93995380-89BD-4b04-88EB-625FBE52EBFB}\"\n\t\t\t>\n\t\t\t<File\n\t\t\t\tRelativePath=\"..\\cmd.h\"\n\t\t\t\t>\n\t\t\t</File>\n\t\t\t<File\n\t\t\t\tRelativePath=\"..\\spshell.h\"\n\t\t\t\t>\n\t\t\t</File>\n\t\t</Filter>\n\t\t<Filter\n\t\t\tName=\"Resource Files\"\n\t\t\tFilter=\"rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx\"\n\t\t\tUniqueIdentifier=\"{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}\"\n\t\t\t>\n\t\t</Filter>\n\t\t<Filter\n\t\t\tName=\"Source Files\"\n\t\t\tFilter=\"cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx\"\n\t\t\tUniqueIdentifier=\"{4FC737F1-C7A5-4376-A066-2A32D752A2FF}\"\n\t\t\t>\n\t\t\t<File\n\t\t\t\tRelativePath=\"..\\..\\appkey.c\"\n\t\t\t\t>\n\t\t\t</File>\n\t\t\t<File\n\t\t\t\tRelativePath=\"..\\browse.c\"\n\t\t\t\t>\n\t\t\t</File>\n\t\t\t<File\n\t\t\t\tRelativePath=\"..\\cmd.c\"\n\t\t\t\t>\n\t\t\t</File>\n\t\t\t<File\n\t\t\t\tRelativePath=\"..\\inbox.c\"\n\t\t\t\t>\n\t\t\t</File>\n\t\t\t<File\n\t\t\t\tRelativePath=\"..\\playlist.c\"\n\t\t\t\t>\n\t\t\t</File>\n\t\t\t<File\n\t\t\t\tRelativePath=\"..\\search.c\"\n\t\t\t\t>\n\t\t\t</File>\n\t\t\t<File\n\t\t\t\tRelativePath=\"..\\spshell.c\"\n\t\t\t\t>\n\t\t\t</File>\n\t\t\t<File\n\t\t\t\tRelativePath=\"..\\spshell_win32.c\"\n\t\t\t\t>\n\t\t\t</File>\n\t\t\t<File\n\t\t\t\tRelativePath=\"..\\star.c\"\n\t\t\t\t>\n\t\t\t</File>\n\t\t\t<File\n\t\t\t\tRelativePath=\"..\\test.c\"\n\t\t\t\t>\n\t\t\t</File>\n\t\t\t<File\n\t\t\t\tRelativePath=\"..\\toplist.c\"\n\t\t\t\t>\n\t\t\t</File>\n\t\t</Filter>\n\t</Files>\n\t<Globals>\n\t</Globals>\n</VisualStudioProject>\n"
  },
  {
    "path": "libspotify/examples/spshell/win32/spshell.vcxproj",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<Project DefaultTargets=\"Build\" ToolsVersion=\"4.0\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\n  <ItemGroup Label=\"ProjectConfigurations\">\n    <ProjectConfiguration Include=\"Debug|Win32\">\n      <Configuration>Debug</Configuration>\n      <Platform>Win32</Platform>\n    </ProjectConfiguration>\n    <ProjectConfiguration Include=\"Release|Win32\">\n      <Configuration>Release</Configuration>\n      <Platform>Win32</Platform>\n    </ProjectConfiguration>\n  </ItemGroup>\n  <PropertyGroup Label=\"Globals\">\n    <ProjectGuid>{6C49596C-977E-4BB6-BC94-123AEB5E2724}</ProjectGuid>\n    <Keyword>Win32Proj</Keyword>\n  </PropertyGroup>\n  <Import Project=\"$(VCTargetsPath)\\Microsoft.Cpp.Default.props\" />\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\" Label=\"Configuration\">\n    <ConfigurationType>Application</ConfigurationType>\n  </PropertyGroup>\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\" Label=\"Configuration\">\n    <ConfigurationType>Application</ConfigurationType>\n  </PropertyGroup>\n  <Import Project=\"$(VCTargetsPath)\\Microsoft.Cpp.props\" />\n  <ImportGroup Label=\"ExtensionSettings\">\n  </ImportGroup>\n  <ImportGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\" Label=\"PropertySheets\">\n    <Import Project=\"$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props\" Condition=\"exists('$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props')\" Label=\"LocalAppDataPlatform\" />\n  </ImportGroup>\n  <ImportGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\" Label=\"PropertySheets\">\n    <Import Project=\"$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props\" Condition=\"exists('$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props')\" Label=\"LocalAppDataPlatform\" />\n  </ImportGroup>\n  <PropertyGroup Label=\"UserMacros\" />\n  <PropertyGroup>\n    <_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion>\n    <OutDir Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\">Debug\\</OutDir>\n    <IntDir Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\">Debug\\</IntDir>\n    <LinkIncremental Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\">true</LinkIncremental>\n    <OutDir Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\">Release\\</OutDir>\n    <IntDir Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\">Release\\</IntDir>\n    <LinkIncremental Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\">false</LinkIncremental>\n    <CodeAnalysisRuleSet Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\">AllRules.ruleset</CodeAnalysisRuleSet>\n    <CodeAnalysisRules Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\" />\n    <CodeAnalysisRuleAssemblies Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\" />\n    <CodeAnalysisRuleSet Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\">AllRules.ruleset</CodeAnalysisRuleSet>\n    <CodeAnalysisRules Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\" />\n    <CodeAnalysisRuleAssemblies Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\" />\n  </PropertyGroup>\n  <ItemDefinitionGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\">\n    <ClCompile>\n      <Optimization>Disabled</Optimization>\n      <AdditionalIncludeDirectories>$(LIBSPOTIFY)\\include;..\\..\\..\\include</AdditionalIncludeDirectories>\n      <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>\n      <MinimalRebuild>true</MinimalRebuild>\n      <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>\n      <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>\n      <PrecompiledHeader>\n      </PrecompiledHeader>\n      <WarningLevel>Level3</WarningLevel>\n      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>\n      <CallingConvention>StdCall</CallingConvention>\n    </ClCompile>\n    <Link>\n      <AdditionalDependencies>libspotify.lib</AdditionalDependencies>\n      <AdditionalLibraryDirectories>$(LIBSPOTIFY)\\lib;..\\..\\..\\lib</AdditionalLibraryDirectories>\n      <GenerateDebugInformation>true</GenerateDebugInformation>\n      <SubSystem>Console</SubSystem>\n      <RandomizedBaseAddress>false</RandomizedBaseAddress>\n      <DataExecutionPrevention>\n      </DataExecutionPrevention>\n      <TargetMachine>MachineX86</TargetMachine>\n    </Link>\n  </ItemDefinitionGroup>\n  <ItemDefinitionGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\">\n    <ClCompile>\n      <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>\n      <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>\n      <PrecompiledHeader>\n      </PrecompiledHeader>\n      <WarningLevel>Level3</WarningLevel>\n      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>\n      <AdditionalIncludeDirectories>$(LIBSPOTIFY)\\include;..\\..\\..\\include</AdditionalIncludeDirectories>\n    </ClCompile>\n    <Link>\n      <GenerateDebugInformation>true</GenerateDebugInformation>\n      <SubSystem>Console</SubSystem>\n      <OptimizeReferences>true</OptimizeReferences>\n      <EnableCOMDATFolding>true</EnableCOMDATFolding>\n      <RandomizedBaseAddress>false</RandomizedBaseAddress>\n      <DataExecutionPrevention>\n      </DataExecutionPrevention>\n      <TargetMachine>MachineX86</TargetMachine>\n      <AdditionalDependencies>libspotify.lib</AdditionalDependencies>\n      <AdditionalLibraryDirectories>$(LIBSPOTIFY)\\lib;..\\..\\..\\lib</AdditionalLibraryDirectories>\n    </Link>\n  </ItemDefinitionGroup>\n  <ItemGroup>\n    <ClInclude Include=\"..\\cmd.h\" />\n    <ClInclude Include=\"..\\spshell.h\" />\n  </ItemGroup>\n  <ItemGroup>\n    <ClCompile Include=\"..\\..\\appkey.c\" />\n    <ClCompile Include=\"..\\browse.c\" />\n    <ClCompile Include=\"..\\cmd.c\" />\n    <ClCompile Include=\"..\\inbox.c\" />\n    <ClCompile Include=\"..\\playlist.c\" />\n    <ClCompile Include=\"..\\search.c\" />\n    <ClCompile Include=\"..\\spshell.c\" />\n    <ClCompile Include=\"..\\spshell_win32.c\" />\n    <ClCompile Include=\"..\\star.c\" />\n    <ClCompile Include=\"..\\test.c\" />\n    <ClCompile Include=\"..\\toplist.c\" />\n  </ItemGroup>\n  <Import Project=\"$(VCTargetsPath)\\Microsoft.Cpp.targets\" />\n  <ImportGroup Label=\"ExtensionTargets\">\n  </ImportGroup>\n</Project>"
  },
  {
    "path": "libspotify/examples/spshell/win32/spshell.vcxproj.filters",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<Project ToolsVersion=\"4.0\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\n  <ItemGroup>\n    <Filter Include=\"Header Files\">\n      <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>\n      <Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>\n    </Filter>\n    <Filter Include=\"Resource Files\">\n      <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>\n      <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx</Extensions>\n    </Filter>\n    <Filter Include=\"Source Files\">\n      <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>\n      <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>\n    </Filter>\n  </ItemGroup>\n  <ItemGroup>\n    <ClInclude Include=\"..\\cmd.h\">\n      <Filter>Header Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"..\\spshell.h\">\n      <Filter>Header Files</Filter>\n    </ClInclude>\n  </ItemGroup>\n  <ItemGroup>\n    <ClCompile Include=\"..\\..\\appkey.c\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"..\\browse.c\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"..\\cmd.c\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"..\\inbox.c\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"..\\search.c\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"..\\spshell.c\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"..\\spshell_win32.c\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"..\\star.c\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"..\\toplist.c\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"..\\playlist.c\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"..\\test.c\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n  </ItemGroup>\n</Project>"
  },
  {
    "path": "libspotify/examples/stub/Makefile",
    "content": "TARGET=posix_stu\nCFLAGs += -Werror\n\ninclude ../common.mk\n\n$(TARGET): main.o\n\t$(CC) $(CFLAGS) $(LDFLAGS) $(LDLIBS) $^ -o $@\n\nifdef DEBUG\nifeq ($(shell uname),Darwin)\n\tinstall_name_tool -change @loader_path/../Frameworks/libspotify.framework/libspotify @rpath/libspotify.so $@\nendif\nendif\n"
  },
  {
    "path": "libspotify/examples/stub/main.c",
    "content": "/**\n * Copyright (c) 2006-2010 Spotify Ltd\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n *\n */\n\n#define USER_AGENT \"<Add your own useragent>\"\n#error Please update above variables for your project\n/* A simple stub that logs in and out */\n\n#include \"main.h\"\n#include <pthread.h>\n#include <sys/time.h>\n#include <stdlib.h>\n#include <stdio.h>\nsp_session *g_session;\n\nstatic int notify_events;\nstatic pthread_mutex_t notify_mutex;\nstatic pthread_cond_t notify_cond;\n\n\nstatic void connection_error(sp_session *session, sp_error error)\n{\n\t\n}\n\nstatic void logged_in(sp_session *session, sp_error error)\n{\n\t//add your testcode here \n\t\n}\n\nstatic void logged_out(sp_session *session)\n{\n\texit(0);\n}\n\n\n/**\n * This callback is called for log messages.\n *\n * @sa sp_session_callbacks#log_message\n */\nstatic void log_message(sp_session *session, const char *data)\n{\n\tfprintf(stderr,\"%s\",data);\n}\n\nvoid notify_main_thread(sp_session *session)\n{\n\tpthread_mutex_lock(&notify_mutex);\n\tnotify_events = 1;\n\tpthread_cond_signal(&notify_cond);\n\tpthread_mutex_unlock(&notify_mutex);\n}\n\nstatic sp_session_callbacks callbacks = {\n\t&logged_in,\n\t&logged_out,\n\tNULL,\n\t&connection_error,\n\tNULL,\n\t&notify_main_thread,\n\tNULL,\n\tNULL,\n\t&log_message\n};\n\nint spotify_init(const char *username,const char *password)\n{\n\tsp_session_config config;\n\tsp_error error;\n\tsp_session *session;\n\t\n\t/// The application key is specific to each project, and allows Spotify\n\t/// to produce statistics on how our service is used.\n\textern const char g_appkey[];\n\t/// The size of the application key.\n\textern const size_t g_appkey_size;\n\n\t// Always do this. It allows libspotify to check for\n\t// header/library inconsistencies.\n\tconfig.api_version = SPOTIFY_API_VERSION;\n\n\t// The path of the directory to store the cache. This must be specified.\n\t// Please read the documentation on preferred values.\n\tconfig.cache_location = \"tmp\";\n\n\t// The path of the directory to store the settings. \n\t// This must be specified.\n\t// Please read the documentation on preferred values.\n\tconfig.settings_location = \"tmp\";\n\n\t// The key of the application. They are generated by Spotify,\n\t// and are specific to each application using libspotify.\n\tconfig.application_key = g_appkey;\n\tconfig.application_key_size = g_appkey_size;\n\n\t// This identifies the application using some\n\t// free-text string [1, 255] characters.\n\tconfig.user_agent = USER_AGENT;\n\n\t// Register the callbacks.\n\tconfig.callbacks = &callbacks;\n\n\terror = sp_session_create(&config, &session);\n\tif (SP_ERROR_OK != error) {\n\t\tfprintf(stderr, \"failed to create session: %s\\n\",\n\t\t                sp_error_message(error));\n\t\treturn 2;\n\t}\n\n\t// Login using the credentials given on the command line.\n\terror = sp_session_login(session, username, password, 0);\n\n\tif (SP_ERROR_OK != error) {\n\t\tfprintf(stderr, \"failed to login: %s\\n\",\n\t\t                sp_error_message(error));\n\t\treturn 3;\n\t}\n\n\tg_session = session;\n\treturn 0;\n}\n\nint main(int argc, char **argv)\n{\n\tint next_timeout = 0;\n\tif(argc < 3) {\n\t\tfprintf(stderr,\"Usage: %s <username> <password>\\n\",argv[0]);\n\t}\n\tpthread_mutex_init(&notify_mutex, NULL);\n\tpthread_cond_init(&notify_cond, NULL);\n\n\tif(spotify_init(argv[1],argv[2]) != 0) {\n\t\tfprintf(stderr,\"Spotify failed to initialize\\n\");\n\t\texit(-1);\n\t}\n\tpthread_mutex_lock(&notify_mutex);\n\tfor (;;) {\n\t\tif (next_timeout == 0) {\n\t\t\twhile(!notify_events)\n\t\t\t\tpthread_cond_wait(&notify_cond, &notify_mutex);\n\t\t} else {\n\t\t\tstruct timespec ts;\n\n\t#if _POSIX_TIMERS > 0\n\t\t\tclock_gettime(CLOCK_REALTIME, &ts);\n\t#else\n\t\t\tstruct timeval tv;\n\t\t\tgettimeofday(&tv, NULL);\n\t\t\tTIMEVAL_TO_TIMESPEC(&tv, &ts);\n\t#endif\n\n\t\t\tts.tv_sec += next_timeout / 1000;\n\t\t\tts.tv_nsec += (next_timeout % 1000) * 1000000;\n\n\t\t\twhile(!notify_events) {\n\t\t\t\tif(pthread_cond_timedwait(&notify_cond, &notify_mutex, &ts))\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\t// Process libspotify events\n\t\tnotify_events = 0;\n\t\tpthread_mutex_unlock(&notify_mutex);\n\n\t\tdo {\n\t\t\tsp_session_process_events(g_session, &next_timeout);\n\t\t} while (next_timeout == 0);\n\n\t\tpthread_mutex_lock(&notify_mutex);\n\t}\n\treturn 0;\n}\n"
  },
  {
    "path": "libspotify/examples/stub/main.h",
    "content": "#ifndef __MAIN_H__\n#define __MAIN_H__\n#include <libspotify/api.h>\n#endif\n"
  },
  {
    "path": "libspotify/include/libspotify/api.h",
    "content": "/*\n * Copyright (c) 2006-2012 Spotify Ltd\n *\n * The terms of use for this and related files can be read in\n * the associated LICENSE file, usually stored in share/doc/libspotify/LICENSE.\n */\n\n/**\n * @file   api.h    Public API for libspotify\n *\n * @note   All input strings are expected to be in UTF-8\n * @note   All output strings are in UTF-8.\n *\n * @note   All usernames are valid XMPP nodeprep identifiers:\n *         http://tools.ietf.org/html/rfc3920#appendix-A\n *         If you need to store user data, we strongly advise you\n *         to use the canonical form of the username.\n */\n\n#ifndef PUBLIC_API_H\n#define PUBLIC_API_H\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n#ifndef SP_CALLCONV\n#ifdef _WIN32\n#define SP_CALLCONV __stdcall\n#else\n#define SP_CALLCONV\n#endif\n#endif\n\n#ifndef SP_LIBEXPORT\n#ifdef _WIN32\n#define SP_LIBEXPORT(x) x __stdcall\n#else\n#define SP_LIBEXPORT(x) x\n#endif\n#endif\n\n/* Includes */\n#include <stddef.h>\n\n#ifdef _WIN32\ntypedef unsigned __int64 sp_uint64;\n#else\n#include <stdint.h>\ntypedef uint64_t sp_uint64;\n#endif\n\n/* General types */\n\n#if !defined(__cplusplus) && !defined(__bool_true_false_are_defined)\ntypedef unsigned char bool;\n#endif\n\ntypedef unsigned char byte;\n\n/**\n * @defgroup types Spotify types & structs\n *\n * @{\n */\n\ntypedef struct sp_session sp_session; ///< Representation of a session\ntypedef struct sp_track sp_track; ///< A track handle\ntypedef struct sp_album sp_album; ///< An album handle\ntypedef struct sp_artist sp_artist; ///< An artist handle\ntypedef struct sp_artistbrowse sp_artistbrowse; ///< A handle to an artist browse result\ntypedef struct sp_albumbrowse sp_albumbrowse; ///< A handle to an album browse result\ntypedef struct sp_toplistbrowse sp_toplistbrowse; ///< A handle to a toplist browse result\ntypedef struct sp_search sp_search; ///< A handle to a search result\ntypedef struct sp_link sp_link; ///< A handle to the libspotify internal representation of a URI\ntypedef struct sp_image sp_image; ///< A handle to an image\ntypedef struct sp_user sp_user; ///< A handle to a user\ntypedef struct sp_playlist sp_playlist; ///< A playlist handle\ntypedef struct sp_playlistcontainer sp_playlistcontainer; ///< A playlist container (playlist containing other playlists) handle\ntypedef struct sp_inbox sp_inbox; ///< Add to inbox request handle\n/** @} */\n\n/**\n * @defgroup error Error Handling\n *\n * All functions in libspotify use the same set of error codes. Most of them return\n * an error code, and let the result of the operation be stored in an out-parameter.\n *\n * @{\n */\n\n/**\n * Error codes returned by various functions\n */\ntypedef enum sp_error {\n  SP_ERROR_OK                        = 0,  ///< No errors encountered\n  SP_ERROR_BAD_API_VERSION           = 1,  ///< The library version targeted does not match the one you claim you support\n  SP_ERROR_API_INITIALIZATION_FAILED = 2,  ///< Initialization of library failed - are cache locations etc. valid?\n  SP_ERROR_TRACK_NOT_PLAYABLE        = 3,  ///< The track specified for playing cannot be played\n  SP_ERROR_BAD_APPLICATION_KEY       = 5,  ///< The application key is invalid\n  SP_ERROR_BAD_USERNAME_OR_PASSWORD  = 6,  ///< Login failed because of bad username and/or password\n  SP_ERROR_USER_BANNED               = 7,  ///< The specified username is banned\n  SP_ERROR_UNABLE_TO_CONTACT_SERVER  = 8,  ///< Cannot connect to the Spotify backend system\n  SP_ERROR_CLIENT_TOO_OLD            = 9,  ///< Client is too old, library will need to be updated\n  SP_ERROR_OTHER_PERMANENT           = 10, ///< Some other error occurred, and it is permanent (e.g. trying to relogin will not help)\n  SP_ERROR_BAD_USER_AGENT            = 11, ///< The user agent string is invalid or too long\n  SP_ERROR_MISSING_CALLBACK          = 12, ///< No valid callback registered to handle events\n  SP_ERROR_INVALID_INDATA            = 13, ///< Input data was either missing or invalid\n  SP_ERROR_INDEX_OUT_OF_RANGE        = 14, ///< Index out of range\n  SP_ERROR_USER_NEEDS_PREMIUM        = 15, ///< The specified user needs a premium account\n  SP_ERROR_OTHER_TRANSIENT           = 16, ///< A transient error occurred.\n  SP_ERROR_IS_LOADING                = 17, ///< The resource is currently loading\n  SP_ERROR_NO_STREAM_AVAILABLE       = 18, ///< Could not find any suitable stream to play\n  SP_ERROR_PERMISSION_DENIED         = 19, ///< Requested operation is not allowed\n  SP_ERROR_INBOX_IS_FULL             = 20, ///< Target inbox is full\n  SP_ERROR_NO_CACHE                  = 21, ///< Cache is not enabled\n  SP_ERROR_NO_SUCH_USER              = 22, ///< Requested user does not exist\n  SP_ERROR_NO_CREDENTIALS            = 23, ///< No credentials are stored\n  SP_ERROR_NETWORK_DISABLED          = 24, ///< Network disabled\n  SP_ERROR_INVALID_DEVICE_ID         = 25, ///< Invalid device ID\n  SP_ERROR_CANT_OPEN_TRACE_FILE      = 26, ///< Unable to open trace file\n  SP_ERROR_APPLICATION_BANNED        = 27, ///< This application is no longer allowed to use the Spotify service\n  SP_ERROR_OFFLINE_TOO_MANY_TRACKS   = 31, ///< Reached the device limit for number of tracks to download\n  SP_ERROR_OFFLINE_DISK_CACHE        = 32, ///< Disk cache is full so no more tracks can be downloaded to offline mode\n  SP_ERROR_OFFLINE_EXPIRED           = 33, ///< Offline key has expired, the user needs to go online again\n  SP_ERROR_OFFLINE_NOT_ALLOWED       = 34, ///< This user is not allowed to use offline mode\n  SP_ERROR_OFFLINE_LICENSE_LOST      = 35, ///< The license for this device has been lost. Most likely because the user used offline on three other device\n  SP_ERROR_OFFLINE_LICENSE_ERROR     = 36, ///< The Spotify license server does not respond correctly\n  SP_ERROR_LASTFM_AUTH_ERROR         = 39, ///< A LastFM scrobble authentication error has occurred\n  SP_ERROR_INVALID_ARGUMENT          = 40, ///< An invalid argument was specified\n  SP_ERROR_SYSTEM_FAILURE            = 41, ///< An operating system error\n} sp_error;\n\n/**\n * Convert a numeric libspotify error code to a text string. The error message is in\n * English. This function is useful for logging purposes.\n *\n * @param[in]   error   The error code to lookup\n */\nSP_LIBEXPORT(const char*) sp_error_message(sp_error error);\n\n/** @} */\n\n\n\n/**\n * @defgroup session Session handling\n *\n * The concept of a session is fundamental for all communication with the Spotify ecosystem - it is the\n * object responsible for communicating with the Spotify service. You will need to instantiate a\n * session that then can be used to request artist information, perform searches etc.\n *\n * @{\n */\n\n/**\n * Current version of the application interface, that is, the API described by this file.\n *\n * This value should be set in the sp_session_config struct passed to sp_session_create().\n *\n * If an (upgraded) library is no longer compatible with this version the error #SP_ERROR_BAD_API_VERSION will be\n * returned from sp_session_create(). Future versions of the library will provide you with some kind of mechanism\n * to request an updated version of the library.\n */\n#define SPOTIFY_API_VERSION 12\n\n/**\n * Describes the current state of the connection\n */\ntypedef enum sp_connectionstate {\n  SP_CONNECTION_STATE_LOGGED_OUT   = 0, ///< User not yet logged in\n  SP_CONNECTION_STATE_LOGGED_IN    = 1, ///< Logged in against a Spotify access point\n  SP_CONNECTION_STATE_DISCONNECTED = 2, ///< Was logged in, but has now been disconnected\n  SP_CONNECTION_STATE_UNDEFINED    = 3, ///< The connection state is undefined\n  SP_CONNECTION_STATE_OFFLINE    = 4  ///< Logged in in offline mode\n} sp_connectionstate;\n\n\n/**\n * Sample type descriptor\n */\ntypedef enum sp_sampletype {\n  SP_SAMPLETYPE_INT16_NATIVE_ENDIAN = 0, ///< 16-bit signed integer samples\n} sp_sampletype;\n\n/**\n * Audio format descriptor\n */\ntypedef struct sp_audioformat {\n  sp_sampletype sample_type;   ///< Sample type enum,\n  int sample_rate;             ///< Audio sample rate, in samples per second.\n  int channels;                ///< Number of channels. Currently 1 or 2.\n} sp_audioformat;\n\n/**\n * Bitrate definitions for music streaming\n */\ntypedef enum sp_bitrate {\n  SP_BITRATE_160k      = 0, ///< Bitrate 160kbps\n  SP_BITRATE_320k      = 1, ///< Bitrate 320kbps\n  SP_BITRATE_96k       = 2, ///< Bitrate 96kbps\n} sp_bitrate;\n\n/**\n * Playlist types\n */\ntypedef enum sp_playlist_type {\n  SP_PLAYLIST_TYPE_PLAYLIST     = 0, ///< A normal playlist.\n  SP_PLAYLIST_TYPE_START_FOLDER = 1, ///< Marks a folder starting point,\n  SP_PLAYLIST_TYPE_END_FOLDER   = 2, ///< and ending point.\n  SP_PLAYLIST_TYPE_PLACEHOLDER  = 3, ///< Unknown entry.\n} sp_playlist_type;\n\n\n\n/**\n * Search types\n */\ntypedef enum sp_search_type {\n  SP_SEARCH_STANDARD  = 0,\n  SP_SEARCH_SUGGEST = 1,\n} sp_search_type;\n\n/**\n * Playlist offline status\n */\ntypedef enum sp_playlist_offline_status {\n  SP_PLAYLIST_OFFLINE_STATUS_NO          = 0, ///< Playlist is not offline enabled\n  SP_PLAYLIST_OFFLINE_STATUS_YES         = 1, ///< Playlist is synchronized to local storage\n  SP_PLAYLIST_OFFLINE_STATUS_DOWNLOADING = 2, ///< This playlist is currently downloading. Only one playlist can be in this state any given time\n  SP_PLAYLIST_OFFLINE_STATUS_WAITING     = 3, ///< Playlist is queued for download\n} sp_playlist_offline_status;\n\n/**\n * Track availability\n */\ntypedef enum sp_availability {\n  SP_TRACK_AVAILABILITY_UNAVAILABLE = 0, ///< Track is not available\n  SP_TRACK_AVAILABILITY_AVAILABLE   = 1, ///< Track is available and can be played\n  SP_TRACK_AVAILABILITY_NOT_STREAMABLE = 2, ///< Track can not be streamed using this account\n  SP_TRACK_AVAILABILITY_BANNED_BY_ARTIST = 3, ///< Track not available on artist's reqeust\n} sp_track_availability;\n\n/**\n * Track offline status\n */\ntypedef enum sp_track_offline_status {\n  SP_TRACK_OFFLINE_NO             = 0, ///< Not marked for offline\n  SP_TRACK_OFFLINE_WAITING        = 1, ///< Waiting for download\n  SP_TRACK_OFFLINE_DOWNLOADING    = 2, ///< Currently downloading\n  SP_TRACK_OFFLINE_DONE           = 3, ///< Downloaded OK and can be played\n  SP_TRACK_OFFLINE_ERROR          = 4, ///< Error during download\n  SP_TRACK_OFFLINE_DONE_EXPIRED   = 5, ///< Downloaded OK but not playable due to expiery\n  SP_TRACK_OFFLINE_LIMIT_EXCEEDED = 6, ///< Waiting because device have reached max number of allowed tracks\n  SP_TRACK_OFFLINE_DONE_RESYNC    = 7, ///< Downloaded OK and available but scheduled for re-download\n} sp_track_offline_status;\n\n/**\n * Image size\n */\ntypedef enum sp_image_size {\n  SP_IMAGE_SIZE_NORMAL                  = 0, ///< Normal image size\n  SP_IMAGE_SIZE_SMALL                   = 1, ///< Small image size\n  SP_IMAGE_SIZE_LARGE                   = 2, ///< Large image size\n} sp_image_size;\n\n/**\n * Buffer stats used by get_audio_buffer_stats callback\n */\ntypedef struct sp_audio_buffer_stats {\n  int samples;                      ///< Samples in buffer\n  int stutter;                      ///< Number of stutters (audio dropouts) since last query\n} sp_audio_buffer_stats;\n\n/**\n * List of subscribers returned by sp_playlist_subscribers()\n */\ntypedef struct sp_subscribers {\n  unsigned int count;    ///< Number of elements in 'subscribers'\n  char *subscribers[1];  ///< Actual size is 'count'. Array of pointers to canonical usernames\n} sp_subscribers;\n\n\n/**\n * Current connection type set using sp_session_set_connection_type()\n */\ntypedef enum sp_connection_type {\n  SP_CONNECTION_TYPE_UNKNOWN        = 0, ///< Connection type unknown (Default)\n  SP_CONNECTION_TYPE_NONE           = 1, ///< No connection\n  SP_CONNECTION_TYPE_MOBILE         = 2, ///< Mobile data (EDGE, 3G, etc)\n  SP_CONNECTION_TYPE_MOBILE_ROAMING = 3, ///< Roamed mobile data (EDGE, 3G, etc)\n  SP_CONNECTION_TYPE_WIFI           = 4, ///< Wireless connection\n  SP_CONNECTION_TYPE_WIRED          = 5, ///< Ethernet cable, etc\n} sp_connection_type;\n\n\n/**\n * Connection rules, bitwise OR of flags\n *\n * The default is SP_CONNECTION_RULE_NETWORK | SP_CONNECTION_RULE_ALLOW_SYNC\n */\ntypedef enum sp_connection_rules {\n  SP_CONNECTION_RULE_NETWORK                = 0x1, ///< Allow network traffic. When not set libspotify will force itself into offline mode\n  SP_CONNECTION_RULE_NETWORK_IF_ROAMING     = 0x2, ///< Allow network traffic even if roaming\n  SP_CONNECTION_RULE_ALLOW_SYNC_OVER_MOBILE = 0x4, ///< Set to allow syncing of offline content over mobile connections\n  SP_CONNECTION_RULE_ALLOW_SYNC_OVER_WIFI   = 0x8, ///< Set to allow syncing of offline content over WiFi\n} sp_connection_rules;\n\n\n/**\n * Controls the type of data that will be included in artist browse queries\n */\ntypedef enum sp_artistbrowse_type {\n  SP_ARTISTBROWSE_FULL,         /**< All information except tophit tracks\n                   This mode is deprecated and will removed in a future release */\n  SP_ARTISTBROWSE_NO_TRACKS,    /**< Only albums and data about them, no tracks.\n             In other words, sp_artistbrowse_num_tracks() will return 0\n              */\n  SP_ARTISTBROWSE_NO_ALBUMS,    /**< Only return data about the artist (artist name, similar artist\n             biography, etc\n             No tracks or album will be abailable.\n             sp_artistbrowse_num_tracks() and sp_artistbrowse_num_albums()\n             will both return 0\n              */\n} sp_artistbrowse_type;\n\ntypedef enum sp_social_provider {\n  SP_SOCIAL_PROVIDER_SPOTIFY,\n  SP_SOCIAL_PROVIDER_FACEBOOK,\n  SP_SOCIAL_PROVIDER_LASTFM,\n} sp_social_provider;\n\ntypedef enum sp_scrobbling_state {\n  SP_SCROBBLING_STATE_USE_GLOBAL_SETTING    = 0,\n  SP_SCROBBLING_STATE_LOCAL_ENABLED         = 1,\n  SP_SCROBBLING_STATE_LOCAL_DISABLED        = 2,\n  SP_SCROBBLING_STATE_GLOBAL_ENABLED        = 3,\n  SP_SCROBBLING_STATE_GLOBAL_DISABLED       = 4,\n} sp_scrobbling_state;\n\n\n/**\n * Offline sync status\n */\ntypedef struct sp_offline_sync_status {\n  /**\n   * Queued tracks/bytes is things left to sync in current sync\n   * operation\n   */\n  int queued_tracks;\n  sp_uint64 queued_bytes;\n\n  /**\n   * Done tracks/bytes is things marked for sync that existed on\n   * device before current sync operation\n   */\n  int done_tracks;\n  sp_uint64 done_bytes;\n\n  /**\n   * Copied tracks/bytes is things that has been copied in\n   * current sync operation\n   */\n  int copied_tracks;\n  sp_uint64 copied_bytes;\n\n  /**\n   * Tracks that are marked as synced but will not be copied\n   * (for various reasons)\n   */\n  int willnotcopy_tracks;\n\n  /**\n   * A track is counted as error when something goes wrong while\n   * syncing the track\n   */\n  int error_tracks;\n\n  /**\n   * Set if sync operation is in progress\n   */\n  bool syncing;\n\n} sp_offline_sync_status;\n\n\n/**\n * Session callbacks\n *\n * Registered when you create a session.\n * If some callbacks should not be of interest, set them to NULL.\n */\ntypedef struct sp_session_callbacks {\n\n  /**\n   * Called when login has been processed and was successful\n   *\n   * @param[in]  session    Session\n   * @param[in]  error      One of the following errors, from ::sp_error\n   *                        SP_ERROR_OK\n   *                        SP_ERROR_CLIENT_TOO_OLD\n   *                        SP_ERROR_UNABLE_TO_CONTACT_SERVER\n   *                        SP_ERROR_BAD_USERNAME_OR_PASSWORD\n   *                        SP_ERROR_USER_BANNED\n   *                        SP_ERROR_USER_NEEDS_PREMIUM\n   *                        SP_ERROR_OTHER_TRANSIENT\n   *                        SP_ERROR_OTHER_PERMANENT\n   */\n  void (SP_CALLCONV *logged_in)(sp_session *session, sp_error error);\n\n  /**\n   * Called when logout has been processed. Either called explicitly\n   * if you initialize a logout operation, or implicitly if there\n   * is a permanent connection error\n   *\n   * @param[in]  session    Session\n   */\n  void (SP_CALLCONV *logged_out)(sp_session *session);\n  /**\n   * Called whenever metadata has been updated\n   *\n   * If you have metadata cached outside of libspotify, you should purge\n   * your caches and fetch new versions.\n   *\n   * @param[in]  session    Session\n   */\n  void (SP_CALLCONV *metadata_updated)(sp_session *session);\n\n  /**\n   * Called when there is a connection error, and the library has problems\n   * reconnecting to the Spotify service. Could be called multiple times (as\n   * long as the problem is present)\n   *\n   *\n   * @param[in]  session    Session\n   * @param[in]  error      One of the following errors, from ::sp_error\n   *                        SP_ERROR_OK\n   *                        SP_ERROR_CLIENT_TOO_OLD\n   *                        SP_ERROR_UNABLE_TO_CONTACT_SERVER\n   *                        SP_ERROR_BAD_USERNAME_OR_PASSWORD\n   *                        SP_ERROR_USER_BANNED\n   *                        SP_ERROR_USER_NEEDS_PREMIUM\n   *                        SP_ERROR_OTHER_TRANSIENT\n   *                        SP_ERROR_OTHER_PERMANENT\n   */\n  void (SP_CALLCONV *connection_error)(sp_session *session, sp_error error);\n\n  /**\n   * Called when the access point wants to display a message to the user\n   *\n   * In the desktop client, these are shown in a blueish toolbar just below the\n   * search box.\n   *\n   * @param[in]  session    Session\n   * @param[in]  message    String in UTF-8 format.\n   */\n  void (SP_CALLCONV *message_to_user)(sp_session *session, const char *message);\n\n  /**\n   * Called when processing needs to take place on the main thread.\n   *\n   * You need to call sp_session_process_events() in the main thread to get\n   * libspotify to do more work. Failure to do so may cause request timeouts,\n   * or a lost connection.\n   *\n   * @param[in]  session    Session\n   *\n   * @note This function is called from an internal session thread - you need to have proper synchronization!\n   */\n  void (SP_CALLCONV *notify_main_thread)(sp_session *session);\n\n  /**\n   * Called when there is decompressed audio data available.\n   *\n   * @param[in]  session    Session\n   * @param[in]  format     Audio format descriptor sp_audioformat\n   * @param[in]  frames     Points to raw PCM data as described by \\p format\n   * @param[in]  num_frames Number of available samples in \\p frames.\n   *                        If this is 0, a discontinuity has occurred (such as after a seek). The application\n   *                        should flush its audio fifos, etc.\n   *\n   * @return                Number of frames consumed.\n   *                        This value can be used to rate limit the output from the library if your\n   *                        output buffers are saturated. The library will retry delivery in about 100ms.\n   *\n   * @note This function is called from an internal session thread - you need to have proper synchronization!\n   *\n   * @note This function must never block. If your output buffers are full you must return 0 to signal\n   *       that the library should retry delivery in a short while.\n   */\n  int (SP_CALLCONV *music_delivery)(sp_session *session, const sp_audioformat *format, const void *frames, int num_frames);\n\n  /**\n   * Music has been paused because an account only allows music\n   * to be played from one location simultaneously.\n   *\n   * @note When this callback is invoked the application should\n   *       behave just as if the user pressed the pause\n   *       button. The application should also display a message\n   *       to the user indicating the playback has been paused\n   *       because another application is playing using the same\n   *       account.\n   *\n   * @note IT MUST NOT automatically resume playback but must\n   *       instead wait for the user to press play.\n   *\n   * @param[in]  session    Session\n   */\n  void (SP_CALLCONV *play_token_lost)(sp_session *session);\n\n  /**\n   * Logging callback.\n   *\n   * @param[in]  session    Session\n   * @param[in]  data       Log data\n   */\n  void (SP_CALLCONV *log_message)(sp_session *session, const char *data);\n\n  /**\n   * End of track.\n   * Called when the currently played track has reached its end.\n   *\n   * @note This function is invoked from the main thread\n   *\n   * @param[in]  session    Session\n   */\n  void (SP_CALLCONV *end_of_track)(sp_session *session);\n\n  /**\n   * Streaming error.\n   * Called when streaming cannot start or continue.\n   *\n   * @note This function is invoked from the main thread\n   *\n   * @param[in]  session    Session\n   * @param[in]  error      One of the following errors, from ::sp_error\n   *                        SP_ERROR_NO_STREAM_AVAILABLE\n   *                        SP_ERROR_OTHER_TRANSIENT\n   *                        SP_ERROR_OTHER_PERMANENT\n   */\n  void (SP_CALLCONV *streaming_error)(sp_session *session, sp_error error);\n\n  /**\n   * Called after user info (anything related to sp_user objects) have been updated.\n   *\n   * @param[in]  session    Session\n   */\n  void (SP_CALLCONV *userinfo_updated)(sp_session *session);\n\n  /**\n   * Called when audio playback should start\n   *\n   * @note For this to work correctly the application must also implement get_audio_buffer_stats()\n   *\n   * @note This function is called from an internal session thread - you need to have proper synchronization!\n   *\n   * @note This function must never block.\n   *\n   * @param[in]  session    Session\n   */\n  void (SP_CALLCONV *start_playback)(sp_session *session);\n\n\n  /**\n   * Called when audio playback should stop\n   *\n   * @note For this to work correctly the application must also implement get_audio_buffer_stats()\n   *\n   * @note This function is called from an internal session thread - you need to have proper synchronization!\n   *\n   * @note This function must never block.\n   *\n   * @param[in]  session    Session\n   */\n  void (SP_CALLCONV *stop_playback)(sp_session *session);\n\n  /**\n   * Called to query application about its audio buffer\n   *\n   * @note This function is called from an internal session thread - you need to have proper synchronization!\n   *\n   * @note This function must never block.\n   *\n   * @param[in]  session    Session\n   * @param[out] stats      Stats struct to be filled by application\n   */\n  void (SP_CALLCONV *get_audio_buffer_stats)(sp_session *session, sp_audio_buffer_stats *stats);\n\n  /**\n   * Called when offline synchronization status is updated\n   *\n   * @param[in]  session    Session\n   */\n  void (SP_CALLCONV *offline_status_updated)(sp_session *session);\n\n  /**\n   * Called when offline synchronization status is updated\n   *\n   * @param[in]  session    Session\n   * @param[in]  error      Offline error. Will be SP_ERROR_OK if the offline synchronization\n   *                        error state has cleared\n   */\n  void (SP_CALLCONV *offline_error)(sp_session *session, sp_error error);\n\n  /**\n   * Called when storable credentials have been updated, usually called when\n   * we have connected to the AP.\n   *\n   * @param[in]  session    Session\n   * @param[in]  blob   Blob is a null-terminated string which contains\n   *        an encrypted token that can be stored safely on disk\n   *        instead of storing plaintext passwords.\n   */\n  void (SP_CALLCONV *credentials_blob_updated)(sp_session *session, const char *blob);\n\n  /**\n   * Called when the connection state has updated - such as when logging in, going offline, etc.\n   *\n   * @param[in]  session    Session\n   */\n  void (SP_CALLCONV *connectionstate_updated)(sp_session *session);\n\n   /**\n  * Called when there is a scrobble error event\n  *\n  * @param[in]  session    Session\n  * @param[in]  error      Scrobble error. Currently SP_ERROR_LASTFM_AUTH_ERROR.\n  */\n  void (SP_CALLCONV *scrobble_error)(sp_session *session, sp_error error);\n\n   /**\n  * Called when there is a change in the private session mode\n  *\n  * @param[in]  session    Session\n  * @param[in]  isPrivate  True if in private session, false otherwhise\n  */\n  void (SP_CALLCONV *private_session_mode_changed)(sp_session *session, bool is_private);\n} sp_session_callbacks;\n\n/**\n * Session config\n */\ntypedef struct sp_session_config {\n  int api_version;                       ///< The version of the Spotify API your application is compiled with. Set to #SPOTIFY_API_VERSION\n  const char *cache_location;            /**< The location where Spotify will write cache files.\n            *   This cache include tracks, cached browse results and coverarts.\n                                          *   Set to empty string (\"\") to disable cache\n            */\n  const char *settings_location;         /**< The location where Spotify will write setting files and per-user\n            *   cache items. This includes playlists, track metadata, etc.\n            *   'settings_location' may be the same path as 'cache_location'.\n            *   'settings_location' folder will not be created (unlike 'cache_location'),\n            *   if you don't want to create the folder yourself, you can set 'settings_location' to 'cache_location'.\n            */\n  const void *application_key;           ///< Your application key\n  size_t application_key_size;           ///< The size of the application key in bytes\n  const char *user_agent;                /**< \"User-Agent\" for your application - max 255 characters long\n                 The User-Agent should be a relevant, customer facing identification of your application\n                 */\n\n  const sp_session_callbacks *callbacks; ///< Delivery callbacks for session events, or NULL if you are not interested in any callbacks (not recommended!)\n  void *userdata;                        ///< User supplied data for your application\n\n  /**\n   * Compress local copy of playlists, reduces disk space usage\n   */\n  bool compress_playlists;\n\n  /**\n   * Don't save metadata for local copies of playlists\n   * Reduces disk space usage at the expense of needing\n   * to request metadata from Spotify backend when loading list\n   */\n  bool dont_save_metadata_for_playlists;\n\n  /**\n   * Avoid loading playlists into RAM on startup.\n   * See sp_playlist_is_in_ram() for more details.\n   */\n  bool initially_unload_playlists;\n\n  /**\n   * Device ID for offline synchronization and logging purposes. The Device Id must be unique to the particular device instance,\n   * i.e. no two units must supply the same Device ID. The Device ID must not change between sessions or power cycles.\n   * Good examples is the device's MAC address or unique serial number.\n   */\n  const char *device_id;\n\n  /**\n   * Url to the proxy server that should be used.\n   * The format is protocol://<host>:port (where protocal is http/https/socks4/socks5)\n   */\n  const char *proxy;\n  /**\n   * Username to authenticate with proxy server\n   */\n  const char *proxy_username;\n  /**\n   * Password to authenticate with proxy server\n   */\n  const char *proxy_password;\n\n\n  /**\n   * Path to API trace file\n   */\n  const char *tracefile;\n\n} sp_session_config;\n\n/**\n * Initialize a session. The session returned will be initialized, but you will need\n * to log in before you can perform any other operation\n * Currently it is not supported to have multiple active sessions, and it's recommended to only call this once per process.\n *\n * Here is a snippet from \\c spshell.c:\n * @dontinclude spshell.c\n * @skip config.api_version\n * @until }\n *\n * @param[in]   config    The configuration to use for the session\n * @param[out]  sess      If successful, a new session - otherwise NULL\n *\n * @return                One of the following errors, from ::sp_error\n *                        SP_ERROR_OK\n *                        SP_ERROR_BAD_API_VERSION\n *                        SP_ERROR_BAD_USER_AGENT\n *                        SP_ERROR_BAD_APPLICATION_KEY\n *                        SP_ERROR_API_INITIALIZATION_FAILED\n *                        SP_ERROR_INVALID_DEVICE_ID\n */\nSP_LIBEXPORT(sp_error) sp_session_create(const sp_session_config *config, sp_session **sess);\n\n/**\n * Release the session. This will clean up all data and connections associated with the session\n *\n * @param[in]   sess      Session object returned from sp_session_create()\n * @return                One of the following errors, from ::sp_error\n *                        SP_ERROR_OK\n */\nSP_LIBEXPORT(sp_error) sp_session_release(sp_session *sess);\n\n\n/**\n * Logs in the specified username/password combo. This initiates the login in the background.\n * A callback is called when login is complete\n *\n * An application MUST NEVER store the user's password in clear text.\n * If automatic relogin is required, use sp_session_relogin()\n *\n * Here is a snippet from \\c spshell.c:\n * @dontinclude spshell.c\n * @skip sp_session_login\n * @until }\n *\n * @param[in]   session             Your session object\n * @param[in]   username            The username to log in\n * @param[in]   password            The password for the specified username\n * @param[in]   remember_me         If set, the username / password will be remembered by libspotify\n * @param[in]   blob              If you have received a blob in the #credentials_blob_updated\n *                                  you can pas this here instead of password\n * @return                          One of the following errors, from ::sp_error\n *                                  SP_ERROR_OK\n */\nSP_LIBEXPORT(sp_error) sp_session_login(sp_session *session, const char *username, const char *password, bool remember_me, const char *blob);\n\n\n/**\n * Log in the remembered user if last user that logged in logged in with remember_me set.\n * If no credentials are stored, this will return SP_ERROR_NO_CREDENTIALS.\n *\n * @param[in]   session      Your session object\n *\n * @return                 One of the following errors, from ::sp_error\n *                         SP_ERROR_OK\n *                         SP_ERROR_NO_CREDENTIALS\n */\nSP_LIBEXPORT(sp_error) sp_session_relogin(sp_session *session);\n\n\n/**\n * Get username of the user that will be logged in via sp_session_relogin()\n *\n * @param[in]   session      Your session object\n * @param[out]  buffer       The buffer to hold the username\n * @param[in]   buffer_size  The max size of the buffer that will hold the username.\n *                           The resulting string is guaranteed to always be null terminated if\n *                           buffer_size > 0\n *\n * @return                   The number of characters in the username.\n *                           If value is greater or equal than \\p buffer_size, output was truncated.\n *                           If returned value is -1 no credentials are stored in libspotify.\n */\nSP_LIBEXPORT(int) sp_session_remembered_user(sp_session *session, char *buffer, size_t buffer_size);\n\n\n/**\n * Get a pointer to a string representing the user's login username.\n *\n * @param[in]   session         Your session object\n *\n * @return                   A string representing the login username.\n */\nSP_LIBEXPORT(const char *) sp_session_user_name(sp_session *session);\n\n\n/**\n * Remove stored credentials in libspotify. If no credentials are currently stored, nothing will happen.\n *\n * @param[in]   session      Your session object\n * @return                   One of the following errors, from ::sp_error\n *                           SP_ERROR_OK\n */\nSP_LIBEXPORT(sp_error) sp_session_forget_me(sp_session *session);\n\n\n/**\n * Fetches the currently logged in user\n *\n * @param[in]   session    Your session object\n *\n * @return                 The logged in user (or NULL if not logged in)\n */\nSP_LIBEXPORT(sp_user *) sp_session_user(sp_session *session);\n\n/**\n * Logs out the currently logged in user\n *\n * Always call this before terminating the application and libspotify is currently\n * logged in. Otherwise, the settings and cache may be lost.\n *\n * @param[in]   session    Your session object\n * @return                 One of the following errors, from ::sp_error\n *                         SP_ERROR_OK\n */\nSP_LIBEXPORT(sp_error) sp_session_logout(sp_session *session);\n\n\n/**\n * Flush the caches\n *\n * This will make libspotify write all data that is meant to be stored\n * on disk to the disk immediately. libspotify does this periodically\n * by itself and also on logout. So under normal conditions this\n * should never need to be used.\n *\n * @param[in]   session    Your session object\n * @return                 One of the following errors, from ::sp_error\n *                         SP_ERROR_OK\n */\nSP_LIBEXPORT(sp_error) sp_session_flush_caches(sp_session *session);\n\n/**\n * The connection state of the specified session.\n *\n * @param[in]   session    Your session object\n *\n * @return                 The connection state - see the sp_connectionstate enum for possible values\n */\nSP_LIBEXPORT(sp_connectionstate) sp_session_connectionstate(sp_session *session);\n\n/**\n * The userdata associated with the session\n *\n * @param[in]   session    Your session object\n *\n * @return                 The userdata that was passed in on session creation\n */\nSP_LIBEXPORT(void *) sp_session_userdata(sp_session *session);\n\n/**\n * Set maximum cache size.\n *\n * @param[in]   session    Your session object\n * @param[in]   size       Maximum cache size in megabytes.\n *                         Setting it to 0 (the default) will let libspotify automatically\n *                         resize the cache (10% of disk free space)\n * @return                 One of the following errors, from ::sp_error\n *                         SP_ERROR_OK\n */\nSP_LIBEXPORT(sp_error) sp_session_set_cache_size(sp_session *session, size_t size);\n\n/**\n * Make the specified session process any pending events\n *\n * @param[in]   session         Your session object\n * @param[out]  next_timeout    Stores the time (in milliseconds) until you should call this function again\n * @return                      One of the following errors, from ::sp_error\n *                              SP_ERROR_OK\n */\nSP_LIBEXPORT(sp_error) sp_session_process_events(sp_session *session, int *next_timeout);\n\n/**\n * Loads the specified track\n *\n * After successfully loading the track, you have the option of running\n * sp_session_player_play() directly, or using sp_session_player_seek() first.\n * When this call returns, the track will have been loaded, unless an error occurred.\n *\n * @param[in]   session    Your session object\n * @param[in]   track      The track to be loaded\n *\n * @return                 One of the following errors, from ::sp_error\n *                         SP_ERROR_OK\n *                         SP_ERROR_MISSING_CALLBACK\n *                         SP_ERROR_TRACK_NOT_PLAYABLE\n *\n */\nSP_LIBEXPORT(sp_error) sp_session_player_load(sp_session *session, sp_track *track);\n\n/**\n * Seek to position in the currently loaded track\n *\n * @param[in]   session    Your session object\n * @param[in]   offset     Track position, in milliseconds.\n * @return                 One of the following errors, from ::sp_error\n *                         SP_ERROR_OK\n */\nSP_LIBEXPORT(sp_error) sp_session_player_seek(sp_session *session, int offset);\n\n/**\n * Play or pause the currently loaded track\n *\n * @param[in]   session    Your session object\n * @param[in]   play       If set to true, playback will occur. If set to false, the playback will be paused.\n * @return                 One of the following errors, from ::sp_error\n *                         SP_ERROR_OK\n */\nSP_LIBEXPORT(sp_error) sp_session_player_play(sp_session *session, bool play);\n\n/**\n * Stops the currently playing track\n *\n * This frees some resources held by libspotify to identify the currently\n * playing track.\n *\n * @param[in]   session    Your session object\n * @return                 One of the following errors, from ::sp_error\n *                         SP_ERROR_OK\n */\nSP_LIBEXPORT(sp_error) sp_session_player_unload(sp_session *session);\n\n/**\n * Prefetch a track\n *\n * Instruct libspotify to start loading of a track into its cache.\n * This could be done by an application just before the current track ends.\n *\n * @param[in]   session    Your session object\n * @param[in]   track      The track to be prefetched\n *\n * @return                 One of the following errors, from ::sp_error\n *                         SP_ERROR_NO_CACHE\n *                         SP_ERROR_OK\n *\n * @note Prefetching is only possible if a cache is configured\n *\n */\nSP_LIBEXPORT(sp_error) sp_session_player_prefetch(sp_session *session, sp_track *track);\n\n/**\n * Returns the playlist container for the currently logged in user.\n *\n * @param[in]   session    Your session object\n *\n * @return                 Playlist container object, NULL if not logged in\n */\nSP_LIBEXPORT(sp_playlistcontainer *) sp_session_playlistcontainer(sp_session *session);\n\n/**\n * Returns an inbox playlist for the currently logged in user\n *\n * @param[in]  session        Session object\n *\n * @return     A playlist or NULL if no user is logged in\n * @note You need to release the playlist when you are done with it.\n * @see sp_playlist_release()\n */\nSP_LIBEXPORT(sp_playlist *) sp_session_inbox_create(sp_session *session);\n\n/**\n * Returns the starred list for the current user\n *\n * @param[in]  session        Session object\n *\n * @return     A playlist or NULL if no user is logged in\n * @note You need to release the playlist when you are done with it.\n * @see sp_playlist_release()\n */\nSP_LIBEXPORT(sp_playlist *) sp_session_starred_create(sp_session *session);\n\n/**\n * Returns the starred list for a user\n *\n * @param[in]  session        Session object\n * @param[in]  canonical_username       Canonical username\n *\n * @return     A playlist or NULL if no user is logged in\n * @note You need to release the playlist when you are done with it.\n * @see sp_playlist_release()\n */\nSP_LIBEXPORT(sp_playlist *) sp_session_starred_for_user_create(sp_session *session, const char *canonical_username);\n\n/**\n * Return the published container for a given @a canonical_username,\n * or the currently logged in user if @a canonical_username is NULL.\n *\n * When done with the list you should call sp_playlistconatiner_release() to\n * decrese the reference you own by having created it.\n *\n * @param[in]   session    Your session object.\n * @param[in]   canonical_username   The canonical username, or NULL.\n *\n * @return Playlist container object, NULL if not logged in.\n */\nSP_LIBEXPORT(sp_playlistcontainer *) sp_session_publishedcontainer_for_user_create(sp_session *session, const char *canonical_username);\n\n\n/**\n * Set preferred bitrate for music streaming\n *\n * @param[in]  session        Session object\n * @param[in]  bitrate        Preferred bitrate, see ::sp_bitrate for possible values\n * @return                    One of the following errors, from ::sp_error\n *                            SP_ERROR_OK\n *                            SP_ERROR_INVALID_ARGUMENT\n */\nSP_LIBEXPORT(sp_error) sp_session_preferred_bitrate(sp_session *session, sp_bitrate bitrate);\n\n\n/**\n * Set preferred bitrate for offline sync\n *\n * @param[in]  session        Session object\n * @param[in]  bitrate        Preferred bitrate, see ::sp_bitrate for possible values\n * @param[in]  allow_resync   Set to true if libspotify should resynchronize already synchronized tracks. Usually you should set this to false.\n * @return                   One of the following errors, from ::sp_error\n *                           SP_ERROR_OK\n *                           SP_ERROR_INVALID_ARGUMENT\n */\nSP_LIBEXPORT(sp_error) sp_session_preferred_offline_bitrate(sp_session *session, sp_bitrate bitrate, bool allow_resync);\n\n\n/**\n * Return status of volume normalization\n *\n * @param[in]  session        Session object\n *\n * @return true iff volume normalization is enabled\n *\n */\nSP_LIBEXPORT(bool) sp_session_get_volume_normalization(sp_session *session);\n\n\n/**\n * Set volume normalization\n *\n * @param[in]  session        Session object\n * @param[in]  on             True iff volume normalization should be enabled\n * @return                    One of the following errors, from ::sp_error\n *                            SP_ERROR_OK\n */\nSP_LIBEXPORT(sp_error) sp_session_set_volume_normalization(sp_session *session, bool on);\n\n\n/**\n * Set if private session is enabled. This disables sharing what the user is listening to\n * to services such as Spotify Social, Facebook and LastFM. The private session will\n * last for a time, and then libspotify will revert to the normal state. The private\n * session is prolonged by user activity.\n *\n * @param[in]  session         Session object\n * @param[in]  enabled         True iff private session should be enabled\n * @return                     One of the following errors, from ::sp_error\n *                             SP_ERROR_OK\n */\nSP_LIBEXPORT(sp_error) sp_session_set_private_session(sp_session *session, bool enabled);\n\n/**\n * Return True if private session is enabled\n *\n * @param[in]  session         Session object\n *\n * @return     True if private session is enabled\n */\nSP_LIBEXPORT(bool) sp_session_is_private_session(sp_session *session);\n\n/**\n * Set if scrobbling is enabled. This api allows setting local overrides of the global scrobbling settings.\n * Changing the global settings are currently not supported.\n *\n * @param[in]  session         Session object\n * @param[in]  provider        The scrobbling provider referred to\n * @param[in]  state           The state to set the provider to\n *\n * @return     error code\n *\n * @see sp_social_provider\n * @see sp_scrobbling_state\n */\nSP_LIBEXPORT(sp_error) sp_session_set_scrobbling(sp_session *session, sp_social_provider provider, sp_scrobbling_state state);\n\n/**\n * Return the scrobbling state. This makes it possible to find out if scrobbling is locally overrided or\n * if the global setting is used.\n *\n * @param[in]  session         Session object\n * @param[in]  provider        The scrobbling provider referred to\n * @param[out] state           The output variable receiving the sp_scrobbling_state state\n *\n * @return     error code\n */\nSP_LIBEXPORT(sp_error) sp_session_is_scrobbling(sp_session *session, sp_social_provider provider, sp_scrobbling_state* state);\n\n/**\n * Return True if scrobbling settings should be shown to the user. Currently this setting is relevant\n * only to the facebook provider.\n * The returned value may be false if the user is not connected to facebook,\n * or if the user has opted out from facebook social graph.\n *\n * @param[in]  session         Session object\n * @param[in]  provider        The scrobbling provider referred to\n * @param[out] out             True iff scrobbling is possible\n *\n * @return     error code\n */\n  SP_LIBEXPORT(sp_error) sp_session_is_scrobbling_possible(sp_session *session, sp_social_provider provider, bool* out);\n\n/**\n * Set the user's credentials with a social provider.\n * Currently this is only relevant for LastFm\n * Call sp_session_set_scrobbling to force an authentication attempt\n * with the LastFm server. If authentication fails a scrobble_error callback will be\n * sent.\n *\n * @param[in]  session         Session object\n * @param[in]  provider        The scrobbling provider referred to\n * @param[in]  username        The user name\n * @param[in]  password        The password\n *\n * @return     error code\n\n * @see sp_session_set_scrobbling\n * @see sp_session_callbacks#scrobble_error\n * @return                     One of the following errors, from ::sp_error\n *                             SP_ERROR_OK\n */\nSP_LIBEXPORT(sp_error) sp_session_set_social_credentials(sp_session *session, sp_social_provider provider, const char* username, const char* password);\n\n/**\n * Set to true if the connection is currently routed over a roamed connectivity\n *\n * @param[in]  session        Session object\n * @param[in]  type           Connection type\n *\n * @note       Used in conjunction with sp_session_set_connection_rules() to control\n *             how libspotify should behave in respect to network activity and offline\n *             synchronization.\n * @see        sp_connection_type\n * @return     One of the following errors, from ::sp_error\n *             SP_ERROR_OK\n */\nSP_LIBEXPORT(sp_error) sp_session_set_connection_type(sp_session *session, sp_connection_type type);\n\n\n/**\n * Set rules for how libspotify connects to Spotify servers and synchronizes offline content\n *\n * @param[in]  session        Session object\n * @param[in]  rules          Connection rules\n *\n * @note       Used in conjunction with sp_session_set_connection_type() to control\n *             how libspotify should behave in respect to network activity and offline\n *             synchronization.\n * @see        sp_connection_rules\n * @return     One of the following errors, from ::sp_error\n *             SP_ERROR_OK\n */\nSP_LIBEXPORT(sp_error) sp_session_set_connection_rules(sp_session *session, sp_connection_rules rules);\n\n\n\n/**\n * Get total number of tracks that needs download before everything\n * from all playlists that is marked for offline is fully synchronized\n *\n * @param[in]  session        Session object\n *\n * @return Number of tracks\n */\nSP_LIBEXPORT(int) sp_offline_tracks_to_sync(sp_session *session);\n\n/**\n * Return number of playlisys that is marked for offline synchronization\n *\n * @param[in]  session        Session object\n *\n * @return Number of playlists\n */\nSP_LIBEXPORT(int) sp_offline_num_playlists(sp_session *session);\n\n/**\n * Return offline synchronization status. When the internal status is\n * updated the offline_status_updated() callback will be invoked.\n *\n * @param[in]  session        Session object\n * @param[out] status         Status object that will be filled with info\n *\n * @return false if no synching is in progress (in which case the contents\n *               of status is undefined)\n *\n */\nSP_LIBEXPORT(bool) sp_offline_sync_get_status(sp_session *session, sp_offline_sync_status *status);\n\n/**\n * Return remaining time (in seconds) until the offline key store expires\n * and the user is required to relogin\n *\n * @param[in]  session        Session object\n * @return                    Seconds until expiration\n *\n */\nSP_LIBEXPORT(int) sp_offline_time_left(sp_session *session);\n\n/**\n * Get currently logged in users country\n * updated the offline_status_updated() callback will be invoked.\n *\n * @param[in]  session        Session object\n *\n * @return  Country encoded in an integer 'SE' = 'S' << 8 | 'E'\n */\nSP_LIBEXPORT(int) sp_session_user_country(sp_session *session);\n\n\n/** @} */\n\n\n/**\n * @defgroup link Links (Spotify URIs)\n *\n * These functions handle links to Spotify entities in a way that allows you to\n * not care about the textual representation of the link.\n * @{\n */\n\n/**\n * Link types\n */\ntypedef enum {\n  SP_LINKTYPE_INVALID  = 0, ///< Link type not valid - default until the library has parsed the link, or when parsing failed\n  SP_LINKTYPE_TRACK    = 1, ///< Link type is track\n  SP_LINKTYPE_ALBUM    = 2, ///< Link type is album\n  SP_LINKTYPE_ARTIST   = 3, ///< Link type is artist\n  SP_LINKTYPE_SEARCH   = 4, ///< Link type is search\n  SP_LINKTYPE_PLAYLIST = 5, ///< Link type is playlist\n  SP_LINKTYPE_PROFILE  = 6, ///< Link type is profile\n  SP_LINKTYPE_STARRED  = 7, ///< Link type is starred\n  SP_LINKTYPE_LOCALTRACK  = 8, ///< Link type is a local file\n  SP_LINKTYPE_IMAGE = 9, ///< Link type is an image\n} sp_linktype;\n\n/**\n * Create a Spotify link given a string\n *\n * @param[in]   link       A string representation of a Spotify link\n *\n * @return                 A link representation of the given string representation.\n *                         If the link could not be parsed, this function returns NULL.\n *\n * @note You need to release the link when you are done with it.\n * @see sp_link_type()\n * @see sp_link_release()\n */\nSP_LIBEXPORT(sp_link *) sp_link_create_from_string(const char *link);\n\n/**\n * Generates a link object from a track\n *\n * @param[in]   track        A track object\n * @param[in]   offset       Offset in track in ms.\n *\n * @return                   A link representing the track\n *\n * @note You need to release the link when you are done with it.\n * @see sp_link_release()\n */\nSP_LIBEXPORT(sp_link *) sp_link_create_from_track(sp_track *track, int offset);\n\n/**\n * Create a link object from an album\n *\n * @param[in]   album      An album object\n *\n * @return                 A link representing the album\n *\n * @note You need to release the link when you are done with it.\n * @see sp_link_release()\n */\nSP_LIBEXPORT(sp_link *) sp_link_create_from_album(sp_album *album);\n\n/**\n * Create an image link object from an album\n *\n * @param[in]   album      An album object\n * @param[in]   size       The desired size of the image\n *\n * @return                 A link representing the album cover. Type is set to SP_LINKTYPE_IMAGE\n *\n * @note You need to release the link when you are done with it.\n * @see sp_link_release()\n */\nSP_LIBEXPORT(sp_link *) sp_link_create_from_album_cover(sp_album *album, sp_image_size size);\n\n/**\n * Creates a link object from an artist\n *\n * @param[in]   artist     An artist object\n *\n * @return                 A link object representing the artist\n *\n * @note You need to release the link when you are done with it.\n * @see sp_link_release()\n */\nSP_LIBEXPORT(sp_link *) sp_link_create_from_artist(sp_artist *artist);\n\n/**\n * Creates a link object pointing to an artist portrait\n *\n * @param[in]   artist     Artist browse object\n * @param[in]   size       The desired size of the image\n *\n * @return                 A link object representing an image\n *\n * @note You need to release the link when you are done with it.\n * @see sp_link_release()\n * @see sp_artistbrowse_num_portraits()\n */\nSP_LIBEXPORT(sp_link *) sp_link_create_from_artist_portrait(sp_artist *artist, sp_image_size size);\n\n\n/**\n * Creates a link object from an artist portrait\n *\n * @param[in]   arb        Artist browse object\n * @param[in]   index      The index of the portrait. Should be in the interval [0, sp_artistbrowse_num_portraits() - 1]\n *\n * @return                 A link object representing an image\n *\n * @note You need to release the link when you are done with it.\n * @see sp_link_release()\n * @see sp_artistbrowse_num_portraits()\n *\n * @note The difference from sp_link_create_from_artist_portrait() is\n * that the artist browse object may contain multiple portraits.\n *\n */\nSP_LIBEXPORT(sp_link *) sp_link_create_from_artistbrowse_portrait(sp_artistbrowse *arb, int index);\n\n\n/**\n * Generate a link object representing the current search\n *\n * @param[in]  search       Search object\n *\n * @return                  A link representing the search\n *\n * @note You need to release the link when you are done with it.\n * @see sp_link_release()\n */\nSP_LIBEXPORT(sp_link *) sp_link_create_from_search(sp_search *search);\n\n/**\n * Create a link object representing the given playlist\n *\n * @param[in]  playlist       Playlist object\n *\n * @return                    A link representing the playlist\n *\n * @note You need to release the link when you are done with it.\n * @see sp_link_release()\n *\n * @note Due to reasons in the playlist backend design and the Spotify URI\n * scheme you need to wait for the playlist to be loaded before you can\n * successfully construct an URI. If sp_link_create_from_playlist() returns\n * NULL, try again after teh playlist_state_changed callback has fired.\n */\nSP_LIBEXPORT(sp_link *) sp_link_create_from_playlist(sp_playlist *playlist);\n\n/**\n * Create a link object representing the given playlist\n *\n * @param[in]  user       User object\n *\n * @return                    A link representing the profile.\n *\n * @note You need to release the link when you are done with it.\n * @see sp_link_release()\n */\nSP_LIBEXPORT(sp_link *) sp_link_create_from_user(sp_user *user);\n\n/**\n * Create a link object representing the given image\n *\n * @param[in]  image          Image object\n *\n * @return                    A link representing the image.\n *\n * @note You need to release the link when you are done with it.\n * @see sp_link_release()\n */\nSP_LIBEXPORT(sp_link *) sp_link_create_from_image(sp_image *image);\n\n/**\n * Create a string representation of the given Spotify link\n *\n * @param[in]   link         The Spotify link whose string representation you are interested in\n * @param[out]  buffer       The buffer to hold the string representation of link\n * @param[in]   buffer_size  The max size of the buffer that will hold the string representation\n *                           The resulting string is guaranteed to always be null terminated if\n *                           buffer_size > 0\n *\n * @return                   The number of characters in the string representation of the link. If this\n *                           value is greater or equal than \\p buffer_size, output was truncated.\n */\nSP_LIBEXPORT(int) sp_link_as_string(sp_link *link, char *buffer, int buffer_size);\n\n/**\n * The link type of the specified link\n *\n * @param[in]   link       The Spotify link whose type you are interested in\n *\n * @return                 The link type of the specified link - see the sp_linktype enum for possible values\n */\nSP_LIBEXPORT(sp_linktype) sp_link_type(sp_link *link);\n\n/**\n * The track representation for the given link\n *\n * @param[in]   link       The Spotify link whose track you are interested in\n *\n * @return                 The track representation of the given track link\n *                         If the link is not of track type then NULL is returned.\n */\nSP_LIBEXPORT(sp_track *) sp_link_as_track(sp_link *link);\n\n/**\n * The track and offset into track representation for the given link\n *\n * @param[in]   link       The Spotify link whose track you are interested in\n * @param[out]  offset     Pointer to offset into track (in milliseconds). If the link\n *                         does not contain an offset this will be set to 0.\n *\n * @return                 The track representation of the given track link\n *                         If the link is not of track type then NULL is returned.\n */\nSP_LIBEXPORT(sp_track *) sp_link_as_track_and_offset(sp_link *link, int *offset);\n\n/**\n * The album representation for the given link\n *\n * @param[in]   link       The Spotify link whose album you are interested in\n *\n * @return                 The album representation of the given album link\n *                         If the link is not of album type then NULL is returned\n */\nSP_LIBEXPORT(sp_album *) sp_link_as_album(sp_link *link);\n\n/**\n * The artist representation for the given link\n *\n * @param[in]   link       The Spotify link whose artist you are interested in\n *\n * @return                 The artist representation of the given link\n *                         If the link is not of artist type then NULL is returned\n */\nSP_LIBEXPORT(sp_artist *) sp_link_as_artist(sp_link *link);\n\n\n/**\n * The user representation for the given link\n *\n * @param[in]   link       The Spotify link whose user you are interested in\n *\n * @return                 The user representation of the given link\n *                         If the link is not of user type then NULL is returned\n */\nSP_LIBEXPORT(sp_user *) sp_link_as_user(sp_link *link);\n\n\n/**\n * Increase the reference count of a link\n *\n * @param[in]   link       The link object\n * @return                 One of the following errors, from ::sp_error\n *                         SP_ERROR_OK\n */\nSP_LIBEXPORT(sp_error) sp_link_add_ref(sp_link *link);\n\n/**\n * Decrease the reference count of a link\n *\n * @param[in]   link       The link object\n * @return                 One of the following errors, from ::sp_error\n *                         SP_ERROR_OK\n */\nSP_LIBEXPORT(sp_error) sp_link_release(sp_link *link);\n\n/** @} */\n\n\n\n/**\n * @defgroup track Track subsystem\n * @{\n */\n\n/**\n * Return whether or not the track metadata is loaded.\n *\n * @param[in]   track      The track\n *\n * @return                 True if track is loaded\n *\n * @note  This is equivalent to checking if sp_track_error() not returns SP_ERROR_IS_LOADING.\n */\nSP_LIBEXPORT(bool) sp_track_is_loaded(sp_track *track);\n\n/**\n * Return an error code associated with a track. For example if it could not load\n *\n * @param[in]   track      The track\n *\n * @return                 One of the following errors, from ::sp_error\n *                         SP_ERROR_OK\n *                         SP_ERROR_IS_LOADING\n *                         SP_ERROR_OTHER_PERMANENT\n */\nSP_LIBEXPORT(sp_error) sp_track_error(sp_track *track);\n\n\n/**\n * Return offline status for a track. sp_session_callbacks::metadata_updated() will be invoked when\n * offline status of a track changes\n *\n * @param[in]   track      The track\n *\n * @return                 Stats as described by ::sp_track_offline_status\n *\n */\nSP_LIBEXPORT(sp_track_offline_status) sp_track_offline_get_status(sp_track *track);\n\n/**\n * Return availability for a track\n *\n * @param[in]   session    Session\n * @param[in]   track      The track\n *\n * @return                 Availability status, see ::sp_track_availability\n *\n * @note The track must be loaded or this function will always SP_TRACK_AVAILABILITY_UNAVAILABLE\n * @see sp_track_is_loaded()\n */\nSP_LIBEXPORT(sp_track_availability) sp_track_get_availability(sp_session *session, sp_track *track);\n\n/**\n * Return true if the track is a local file.\n *\n * @param[in]   session    Session\n * @param[in]   track      The track\n *\n * @return                 True if track is a local file.\n *\n * @note The track must be loaded or this function will always return false.\n * @see sp_track_is_loaded()\n */\nSP_LIBEXPORT(bool) sp_track_is_local(sp_session *session, sp_track *track);\n\n/**\n * Return true if the track is autolinked to another track.\n *\n * @param[in]   session    Session\n * @param[in]   track      The track\n *\n * @return                 True if track is autolinked.\n *\n * @note The track must be loaded or this function will always return false.\n * @see sp_track_is_loaded()\n */\nSP_LIBEXPORT(bool) sp_track_is_autolinked(sp_session *session, sp_track *track);\n\n\n/**\n * Return the actual track that will be played if the given track is played\n *\n * @param[in]   session    Session\n * @param[in]   track      The track\n *\n * @return                 A track\n *\n */\nSP_LIBEXPORT(sp_track *) sp_track_get_playable(sp_session *session, sp_track *track);\n\n/**\n * Return true if the track is a placeholder. Placeholder tracks are used\n * to store other objects than tracks in the playlist. Currently this is\n * used in the inbox to store artists, albums and playlists.\n *\n * Use sp_link_create_from_track() to get a link object that points\n * to the real object this \"track\" points to.\n *\n * @param[in]   track      The track\n *\n * @return                 True if track is a placeholder\n *\n * @note Contrary to most functions the track does not have to be\n *       loaded for this function to return correct value\n */\nSP_LIBEXPORT(bool) sp_track_is_placeholder(sp_track *track);\n\n\n/**\n * Return true if the track is starred by the currently logged in user.\n *\n * @param[in]   session    Session\n * @param[in]   track      The track\n *\n * @return                 True if track is starred.\n *\n * @note The track must be loaded or this function will always return false.\n * @see sp_track_is_loaded()\n */\nSP_LIBEXPORT(bool) sp_track_is_starred(sp_session *session, sp_track *track);\n\n/**\n * Star/Unstar the specified track\n *\n * @param[in]   session    Session\n * @param[in]   tracks     Array of pointer to tracks.\n * @param[in]   num_tracks Length of \\p tracks array\n * @param[in]   star       Starred status of the track\n *\n * @note This will fail silently if playlists are disabled.\n * @see sp_set_playlists_enabled()\n */\nSP_LIBEXPORT(sp_error) sp_track_set_starred(sp_session *session, sp_track *const*tracks, int num_tracks, bool star);\n\n/**\n * The number of artists performing on the specified track\n *\n * @param[in]   track     The track whose number of participating artists you are interested in\n *\n * @return                The number of artists performing on the specified track.\n *                        If no metadata is available for the track yet, this function returns 0.\n */\nSP_LIBEXPORT(int) sp_track_num_artists(sp_track *track);\n\n/**\n * The artist matching the specified index performing on the current track.\n *\n * @param[in]   track      The track whose participating artist you are interested in\n * @param[in]   index      The index for the participating artist. Should be in the interval [0, sp_track_num_artists() - 1]\n *\n * @return                 The participating artist, or NULL if invalid index\n */\nSP_LIBEXPORT(sp_artist *) sp_track_artist(sp_track *track, int index);\n\n/**\n * The album of the specified track\n *\n * @param[in]   track      A track object\n *\n * @return                 The album of the given track. You need to increase the refcount\n *                         if you want to keep the pointer around.\n *                         If no metadata is available for the track yet, this function returns 0.\n */\nSP_LIBEXPORT(sp_album *) sp_track_album(sp_track *track);\n\n/**\n * The string representation of the specified track's name\n *\n * @param[in]   track      A track object\n *\n * @return                 The string representation of the specified track's name.\n *                         Returned string is valid as long as the album object stays allocated\n *                         and no longer than the next call to sp_session_process_events()\n *                         If no metadata is available for the track yet, this function returns empty string.\n */\nSP_LIBEXPORT(const char *) sp_track_name(sp_track *track);\n\n/**\n * The duration, in milliseconds, of the specified track\n *\n * @param[in]   track      A track object\n *\n * @return                 The duration of the specified track, in milliseconds\n *                         If no metadata is available for the track yet, this function returns 0.\n */\nSP_LIBEXPORT(int) sp_track_duration(sp_track *track);\n\n/**\n * Returns popularity for track\n *\n * @param[in]   track      A track object\n *\n * @return                 Popularity in range 0 to 100, 0 if undefined.\n *                         If no metadata is available for the track yet, this function returns 0.\n */\nSP_LIBEXPORT(int) sp_track_popularity(sp_track *track);\n\n/**\n * Returns the disc number for a track\n *\n * @param[in]   track      A track object\n *\n * @return                 Disc index. Possible values are [1, total number of discs on album]\n *                         This function returns valid data only for tracks appearing in a browse\n *                         artist or browse album result (otherwise returns 0).\n */\nSP_LIBEXPORT(int) sp_track_disc(sp_track *track);\n\n/**\n * Returns the position of a track on its disc\n *\n * @param[in]   track      A track object\n *\n * @return                 Track position, starts at 1 (relative the corresponding disc)\n *                         This function returns valid data only for tracks appearing in a browse\n *                         artist or browse album result (otherwise returns 0).\n */\nSP_LIBEXPORT(int) sp_track_index(sp_track *track);\n\n/**\n * Returns the newly created local track\n *\n * @param[in]   artist     Name of the artist\n * @param[in]   title      Song title\n * @param[in]   album      Name of the album, or an empty string if not available\n * @param[in]   length      Length in MS, or -1 if not available.\n *\n * @return                 A track.\n */\nSP_LIBEXPORT(sp_track *) sp_localtrack_create(const char *artist, const char *title, const char *album, int length);\n\n/**\n * Increase the reference count of a track\n *\n * @param[in]   track       The track object\n * @return                  One of the following errors, from ::sp_error\n *                          SP_ERROR_OK\n */\nSP_LIBEXPORT(sp_error) sp_track_add_ref(sp_track *track);\n\n/**\n * Decrease the reference count of a track\n *\n * @param[in]   track       The track object\n * @return                  One of the following errors, from ::sp_error\n *                          SP_ERROR_OK\n */\nSP_LIBEXPORT(sp_error) sp_track_release(sp_track *track);\n\n/** @} */\n\n\n\n/**\n * @defgroup album Album subsystem\n * @{\n */\n\n/**\n * Album types\n */\ntypedef enum {\n  SP_ALBUMTYPE_ALBUM       = 0, ///< Normal album\n  SP_ALBUMTYPE_SINGLE      = 1, ///< Single\n  SP_ALBUMTYPE_COMPILATION = 2, ///< Compilation\n  SP_ALBUMTYPE_UNKNOWN     = 3, ///< Unknown type\n} sp_albumtype;\n\n/**\n * Check if the album object is populated with data\n *\n * @param[in]  album       Album object\n * @return True if metadata is present, false if not\n */\nSP_LIBEXPORT(bool) sp_album_is_loaded(sp_album *album);\n\n\n/**\n * Return true if the album is available in the current region.\n *\n * @param[in]   album      The album\n *\n * @return                 True if album is available for playback, otherwise false.\n *\n * @note The album must be loaded or this function will always return false.\n * @see sp_album_is_loaded()\n */\nSP_LIBEXPORT(bool) sp_album_is_available(sp_album *album);\n\n/**\n * Get the artist associated with the given album\n *\n * @param[in]  album       Album object\n * @return A reference to the artist. NULL if the metadata has not been loaded yet\n */\nSP_LIBEXPORT(sp_artist *) sp_album_artist(sp_album *album);\n\n/**\n * Return image ID representing the album's coverart.\n *\n * @param[in]   album      Album object\n * @param[in]   size       The desired size of the image\n *\n * @return                 ID byte sequence that can be passed to sp_image_create()\n *                         If the album has no image or the metadata for the album is not\n *                         loaded yet, this function returns NULL.\n *\n * @see sp_image_create\n */\nSP_LIBEXPORT(const byte *) sp_album_cover(sp_album *album, sp_image_size size);\n\n/**\n * Return name of album\n *\n * @param[in]   album      Album object\n *\n * @return                 Name of album.\n *                         Returned string is valid as long as the album object stays allocated\n *                         and no longer than the next call to sp_session_process_events()\n */\nSP_LIBEXPORT(const char *) sp_album_name(sp_album *album);\n\n/**\n * Return release year of specified album\n *\n * @param[in]   album      Album object\n *\n * @return                 Release year\n */\nSP_LIBEXPORT(int) sp_album_year(sp_album *album);\n\n\n/**\n * Return type of specified album\n *\n * @param[in]   album      Album object\n *\n * @return                 sp_albumtype\n */\nSP_LIBEXPORT(sp_albumtype) sp_album_type(sp_album *album);\n\n\n/**\n * Increase the reference count of an album\n *\n * @param[in]   album       The album object\n * @return                  One of the following errors, from ::sp_error\n *                          SP_ERROR_OK\n */\nSP_LIBEXPORT(sp_error) sp_album_add_ref(sp_album *album);\n\n/**\n * Decrease the reference count of an album\n *\n * @param[in]   album       The album object\n * @return                  One of the following errors, from ::sp_error\n *                          SP_ERROR_OK\n */\nSP_LIBEXPORT(sp_error) sp_album_release(sp_album *album);\n\n/** @} */\n\n\n\n/**\n * @defgroup artist Artist subsystem\n * @{\n */\n\n/**\n * Return name of artist\n *\n * @param[in]   artist     Artist object\n *\n * @return                 Name of artist.\n *                         Returned string is valid as long as the artist object stays allocated\n *                         and no longer than the next call to sp_session_process_events()\n */\nSP_LIBEXPORT(const char *) sp_artist_name(sp_artist *artist);\n\n/**\n * Check if the artist object is populated with data\n *\n * @param[in]   artist     An artist object\n *\n * @return                 True if metadata is present, false if not\n *\n */\nSP_LIBEXPORT(bool) sp_artist_is_loaded(sp_artist *artist);\n\n/**\n * Return portrait for artist\n *\n * @param[in]   artist     The artist object\n * @param[in]   size       The desired size of the image\n *\n * @return                 ID byte sequence that can be passed to sp_image_create()\n *                         If the artist has no image or the metadata for the album is not\n *                         loaded yet, this function returns NULL.\n *\n */\nSP_LIBEXPORT(const byte *) sp_artist_portrait(sp_artist *artist, sp_image_size size);\n\n/**\n * Increase the reference count of a artist\n *\n * @param[in]   artist       The artist object\n * @return                   One of the following errors, from ::sp_error\n *                           SP_ERROR_OK\n */\nSP_LIBEXPORT(sp_error) sp_artist_add_ref(sp_artist *artist);\n\n/**\n * Decrease the reference count of a artist\n *\n * @param[in]   artist       The artist object\n * @return                   One of the following errors, from ::sp_error\n *                           SP_ERROR_OK\n */\nSP_LIBEXPORT(sp_error) sp_artist_release(sp_artist *artist);\n\n/** @} */\n\n\n/**\n * @defgroup albumbrowse Album browsing\n *\n * Browsing adds additional information to what an ::sp_album holds. It retrieves\n * copyrights, reviews and tracks of the album.\n *\n * @{\n */\n\n/**\n * The type of a callback used in sp_albumbrowse_create()\n *\n * When the callback is called, the metadata of all tracks belonging to it will have\n * been loaded, so sp_track_is_loaded() will return non-zero. The ::sp_artist of the\n * album will also have been fully loaded.\n *\n * @param[in]   result          The same pointer returned by sp_albumbrowse_create()\n * @param[in]   userdata        The opaque pointer given to sp_albumbrowse_create()\n */\ntypedef void SP_CALLCONV albumbrowse_complete_cb(sp_albumbrowse *result, void *userdata);\n\n/**\n * Initiate a request for browsing an album\n *\n * The user is responsible for freeing the returned album browse using sp_albumbrowse_release(). This can be done in the callback.\n *\n * @param[in]   session         Session object\n * @param[in]   album           Album to be browsed. The album metadata does not have to be loaded\n * @param[in]   callback        Callback to be invoked when browsing has been completed. Pass NULL if you are not interested in this event.\n * @param[in]   userdata        Userdata passed to callback.\n *\n * @return                      Album browse object\n *\n * @see ::albumbrowse_complete_cb\n */\nSP_LIBEXPORT(sp_albumbrowse *) sp_albumbrowse_create(sp_session *session, sp_album *album, albumbrowse_complete_cb *callback, void *userdata);\n\n/**\n * Check if an album browse request is completed\n *\n * @param[in]   alb        Album browse object\n *\n * @return                 True if browsing is completed, false if not\n */\nSP_LIBEXPORT(bool) sp_albumbrowse_is_loaded(sp_albumbrowse *alb);\n\n\n/**\n* Check if browsing returned an error code.\n*\n* @param[in]   alb        Album browse object\n*\n* @return                 One of the following errors, from ::sp_error\n*                         SP_ERROR_OK\n*                         SP_ERROR_IS_LOADING\n*                         SP_ERROR_OTHER_PERMANENT\n*                         SP_ERROR_OTHER_TRANSIENT\n*/\nSP_LIBEXPORT(sp_error) sp_albumbrowse_error(sp_albumbrowse *alb);\n\n/**\n * Given an album browse object, return the pointer to its album object\n *\n * @param[in]   alb        Album browse object\n *\n * @return                 Album object\n */\nSP_LIBEXPORT(sp_album *) sp_albumbrowse_album(sp_albumbrowse *alb);\n\n/**\n * Given an album browse object, return the pointer to its artist object\n *\n * @param[in]   alb        Album browse object\n *\n * @return                 Artist object\n */\nSP_LIBEXPORT(sp_artist *) sp_albumbrowse_artist(sp_albumbrowse *alb);\n\n/**\n * Given an album browse object, return number of copyright strings\n *\n * @param[in]   alb        Album browse object\n *\n * @return                 Number of copyright strings available, 0 if unknown\n */\nSP_LIBEXPORT(int) sp_albumbrowse_num_copyrights(sp_albumbrowse *alb);\n\n/**\n * Given an album browse object, return one of its copyright strings\n *\n * @param[in]   alb           Album browse object\n * @param[in]   index         The index for the copyright string. Should be in the interval [0, sp_albumbrowse_num_copyrights() - 1]\n *\n * @return                    Copyright string in UTF-8 format, or NULL if the index is invalid.\n *                            Returned string is valid as long as the album object stays allocated\n *                            and no longer than the next call to sp_session_process_events()\n */\nSP_LIBEXPORT(const char *) sp_albumbrowse_copyright(sp_albumbrowse *alb, int index);\n\n/**\n * Given an album browse object, return number of tracks\n *\n * @param[in]   alb         Album browse object\n *\n * @return                  Number of tracks on album\n */\nSP_LIBEXPORT(int) sp_albumbrowse_num_tracks(sp_albumbrowse *alb);\n\n/**\n * Given an album browse object, return a pointer to one of its tracks\n *\n * @param[in]   alb        Album browse object\n * @param[in]   index      The index for the track. Should be in the interval [0, sp_albumbrowse_num_tracks() - 1]\n *\n * @return                 A track.\n *\n * @see track\n */\nSP_LIBEXPORT(sp_track *) sp_albumbrowse_track(sp_albumbrowse *alb, int index);\n\n/**\n * Given an album browse object, return its review\n *\n * @param[in]   alb        Album browse object\n *\n * @return                 Review string in UTF-8 format.\n *                         Returned string is valid as long as the album object stays allocated\n *                         and no longer than the next call to sp_session_process_events()\n */\nSP_LIBEXPORT(const char *) sp_albumbrowse_review(sp_albumbrowse *alb);\n\n/**\n * Return the time (in ms) that was spent waiting for the Spotify backend to serve the request\n *\n * @param[in] alb         Album browse object\n *\n * @return                -1 if the request was served from the local cache\n *                        If the result is not yet loaded the return value is undefined\n */\nSP_LIBEXPORT(int) sp_albumbrowse_backend_request_duration(sp_albumbrowse *alb);\n\n\n/**\n * Increase the reference count of an album browse result\n *\n * @param[in]   alb       The album browse result object\n * @return                One of the following errors, from ::sp_error\n *                        SP_ERROR_OK\n */\nSP_LIBEXPORT(sp_error) sp_albumbrowse_add_ref(sp_albumbrowse *alb);\n\n/**\n * Decrease the reference count of an album browse result\n *\n * @param[in]   alb       The album browse result object\n * @return                One of the following errors, from ::sp_error\n *                        SP_ERROR_OK\n */\nSP_LIBEXPORT(sp_error) sp_albumbrowse_release(sp_albumbrowse *alb);\n\n/** @} */\n\n\n/**\n * @defgroup artistbrowse Artist browsing\n *\n * Artist browsing initiates the fetching of information for a certain artist.\n *\n * @note   There is currently no built-in functionality available for getting the albums belonging\n *         to an artist. For now, just iterate over all tracks and note the album to build a list of all albums.\n *         This feature will be added in a future version of the library.\n *\n * @{\n */\n\n/**\n * The type of a callback used in sp_artistbrowse_create()\n *\n * When the callback is called, the metadata of all tracks belonging to it will have\n * been loaded, so sp_track_is_loaded() will return non-zero. The same goes for the\n * similar artist data.\n *\n * @param[in]   result          The same pointer returned by sp_artistbrowse_create()\n * @param[in]   userdata        The opaque pointer given to sp_artistbrowse_create()\n */\ntypedef void SP_CALLCONV artistbrowse_complete_cb(sp_artistbrowse *result, void *userdata);\n\n/**\n * Initiate a request for browsing an artist\n *\n * The user is responsible for freeing the returned artist browse using sp_artistbrowse_release(). This can be done in the callback.\n *\n * @param[in] session         Session object\n * @param[in] artist          Artist to be browsed. The artist metadata does not have to be loaded\n * @param[in] type            Type of data requested, see the sp_artistbrowse_type enum for details\n * @param[in] callback        Callback to be invoked when browsing has been completed. Pass NULL if you are not interested in this event.\n * @param[in] userdata        Userdata passed to callback.\n *\n * @return                    Artist browse object\n *\n * @see ::artistbrowse_complete_cb\n */\nSP_LIBEXPORT(sp_artistbrowse *) sp_artistbrowse_create(sp_session *session, sp_artist *artist, sp_artistbrowse_type type, artistbrowse_complete_cb *callback, void *userdata);\n\n/**\n * Check if an artist browse request is completed\n *\n * @param[in]   arb        Artist browse object\n *\n * @return                 True if browsing is completed, false if not\n */\nSP_LIBEXPORT(bool) sp_artistbrowse_is_loaded(sp_artistbrowse *arb);\n\n/**\n* Check if browsing returned an error code.\n*\n* @param[in]   arb        Artist browse object\n*\n* @return                 One of the following errors, from ::sp_error\n*                         SP_ERROR_OK\n*                         SP_ERROR_IS_LOADING\n*                         SP_ERROR_OTHER_PERMANENT\n*                         SP_ERROR_OTHER_TRANSIENT\n*/\nSP_LIBEXPORT(sp_error) sp_artistbrowse_error(sp_artistbrowse *arb);\n\n/**\n * Given an artist browse object, return a pointer to its artist object\n *\n * @param[in]   arb        Artist browse object\n *\n * @return                 Artist object\n */\nSP_LIBEXPORT(sp_artist *) sp_artistbrowse_artist(sp_artistbrowse *arb);\n\n/**\n * Given an artist browse object, return number of portraits available\n *\n * @param[in]   arb        Artist browse object\n *\n * @return                 Number of portraits for given artist\n */\nSP_LIBEXPORT(int) sp_artistbrowse_num_portraits(sp_artistbrowse *arb);\n\n/**\n * Return image ID representing a portrait of the artist\n *\n * @param[in] arb             Artist object\n * @param[in] index           The index of the portrait. Should be in the interval [0, sp_artistbrowse_num_portraits() - 1]\n *\n * @return                    ID byte sequence that can be passed to sp_image_create()\n *\n * @see sp_image_create\n */\nSP_LIBEXPORT(const byte *) sp_artistbrowse_portrait(sp_artistbrowse *arb, int index);\n\n/**\n * Given an artist browse object, return number of tracks\n *\n * @param[in] arb             Artist browse object\n *\n * @return                    Number of tracks for given artist\n */\nSP_LIBEXPORT(int) sp_artistbrowse_num_tracks(sp_artistbrowse *arb);\n\n/**\n * Given an artist browse object, return one of its tracks\n *\n * @param[in] arb             Album browse object\n * @param[in] index           The index for the track. Should be in the interval [0, sp_artistbrowse_num_tracks() - 1]\n *\n * @return                    A track object, or NULL if the index is out of range.\n *\n * @see track\n */\nSP_LIBEXPORT(sp_track *) sp_artistbrowse_track(sp_artistbrowse *arb, int index);\n\n\n/**\n * Given an artist browse object, return number of tophit tracks\n * This is a set of tracks for the artist with highest popularity\n *\n * @param[in] arb             Artist browse object\n *\n * @return                    Number of tophit tracks for given artist\n */\nSP_LIBEXPORT(int) sp_artistbrowse_num_tophit_tracks(sp_artistbrowse *arb);\n\n/**\n * Given an artist browse object, return one of its tophit tracks\n * This is a set of tracks for the artist with highest popularity\n *\n * @param[in] arb             Album browse object\n * @param[in] index           The index for the track. Should be in the interval [0, sp_artistbrowse_num_tophit_tracks() - 1]\n *\n * @return                    A track object, or NULL if the index is out of range.\n *\n * @see track\n */\nSP_LIBEXPORT(sp_track *) sp_artistbrowse_tophit_track(sp_artistbrowse *arb, int index);\n\n/**\n * Given an artist browse object, return number of albums\n *\n * @param[in] arb             Artist browse object\n *\n * @return                    Number of albums for given artist\n */\nSP_LIBEXPORT(int) sp_artistbrowse_num_albums(sp_artistbrowse *arb);\n\n/**\n * Given an artist browse object, return one of its albums\n *\n * @param[in] arb             Album browse object\n * @param[in] index           The index for the album. Should be in the interval [0, sp_artistbrowse_num_albums() - 1]\n *\n * @return                    A album object, or NULL if the index is out of range.\n *\n * @see album\n */\nSP_LIBEXPORT(sp_album *) sp_artistbrowse_album(sp_artistbrowse *arb, int index);\n\n/**\n * Given an artist browse object, return number of similar artists\n *\n * @param[in] arb             Artist browse object\n *\n * @return                    Number of similar artists for given artist\n */\nSP_LIBEXPORT(int) sp_artistbrowse_num_similar_artists(sp_artistbrowse *arb);\n\n/**\n * Given an artist browse object, return a similar artist by index\n *\n * @param[in] arb             Album browse object\n * @param[in] index           The index for the artist. Should be in the interval [0, sp_artistbrowse_num_similar_artists() - 1]\n *\n * @return                    A pointer to an artist object.\n *\n * @see artist\n */\nSP_LIBEXPORT(sp_artist *) sp_artistbrowse_similar_artist(sp_artistbrowse *arb, int index);\n\n/**\n * Given an artist browse object, return the artists biography\n *\n * @note This function must be called from the same thread that did sp_session_create()\n * @param[in] arb             Artist browse object\n *\n * @return                    Biography string in UTF-8 format.\n *                            Returned string is valid as long as the album object stays allocated\n *                            and no longer than the next call to sp_session_process_events()\n */\nSP_LIBEXPORT(const char *) sp_artistbrowse_biography(sp_artistbrowse *arb);\n\n/**\n * Return the time (in ms) that was spent waiting for the Spotify backend to serve the request\n *\n * @param[in] arb         Artist browse object\n *\n * @return                -1 if the request was served from the local cache\n *                        If the result is not yet loaded the return value is undefined\n */\nSP_LIBEXPORT(int) sp_artistbrowse_backend_request_duration(sp_artistbrowse *arb);\n\n\n/**\n * Increase the reference count of an artist browse result\n *\n * @param[in]   arb       The artist browse result object\n * @return                One of the following errors, from ::sp_error\n *                        SP_ERROR_OK\n */\nSP_LIBEXPORT(sp_error) sp_artistbrowse_add_ref(sp_artistbrowse *arb);\n\n/**\n * Decrease the reference count of an artist browse result\n *\n * @param[in]   arb       The artist browse result object\n * @return                One of the following errors, from ::sp_error\n *                        SP_ERROR_OK\n */\nSP_LIBEXPORT(sp_error) sp_artistbrowse_release(sp_artistbrowse *arb);\n\n/** @} */\n\n\n\n/**\n * @defgroup image Image handling\n * @{\n */\n\n/**\n * Image format\n */\ntypedef enum {\n  SP_IMAGE_FORMAT_UNKNOWN = -1, ///< Unknown image format\n  SP_IMAGE_FORMAT_JPEG   = 0,   ///< JPEG image\n} sp_imageformat;\n\n/**\n * The type of a callback used to notify the application that an image\n * is done loading.\n */\ntypedef void SP_CALLCONV image_loaded_cb(sp_image *image, void *userdata);\n\n/**\n * Create an image object\n *\n * @param[in]  session    Session\n * @param[in]  image_id   Spotify image ID\n *\n * @return                Pointer to an image object. To free the object, use\n *                        sp_image_release()\n *\n * @see sp_album_cover\n * @see sp_artistbrowse_portrait\n */\nSP_LIBEXPORT(sp_image *) sp_image_create(sp_session *session, const byte image_id[20]);\n\n/**\n * Create an image object from a link\n *\n * @param[in]  session    Session\n * @param[in]  l          Spotify link object. This must be of SP_LINKTYPE_IMAGE type\n *\n * @return                Pointer to an image object. To free the object, use\n *                        sp_image_release()\n *\n * @see sp_image_create\n */\nSP_LIBEXPORT(sp_image *) sp_image_create_from_link(sp_session *session, sp_link *l);\n\n/**\n * Add a callback that will be invoked when the image is loaded\n *\n * If an image is loaded, and loading fails, the image will behave like an\n * empty image.\n *\n * @param[in]  image      Image object\n * @param[in]  callback   Callback that will be called when image has been\n *                        fetched.\n * @param[in]  userdata   Opaque pointer passed to \\p callback\n *\n */\nSP_LIBEXPORT(sp_error) sp_image_add_load_callback(sp_image *image, image_loaded_cb *callback, void *userdata);\n\n/**\n * Remove an image load callback previously added with sp_image_add_load_callback()\n *\n * @param[in]  image      Image object\n * @param[in]  callback   Callback that will not be called when image has been\n *                        fetched.\n * @param[in]  userdata   Opaque pointer passed to \\p callback\n * @return                One of the following errors, from ::sp_error\n *                        SP_ERROR_OK\n */\nSP_LIBEXPORT(sp_error) sp_image_remove_load_callback(sp_image *image, image_loaded_cb *callback, void *userdata);\n\n/**\n * Check if an image is loaded. Before the image is loaded, the rest of the\n * methods will behave as if the image is empty.\n *\n * @param[in]  image      Image object\n *\n * @return                True if image is loaded, false otherwise\n */\nSP_LIBEXPORT(bool) sp_image_is_loaded(sp_image *image);\n\n/**\n* Check if image retrieval returned an error code.\n*\n* @param[in]   image      Image object\n*\n* @return                 One of the following errors, from ::sp_error\n*                         SP_ERROR_OK\n*                         SP_ERROR_IS_LOADING\n*                         SP_ERROR_OTHER_PERMANENT\n*                         SP_ERROR_OTHER_TRANSIENT\n*/\nSP_LIBEXPORT(sp_error) sp_image_error(sp_image *image);\n\n/**\n * Get image format\n *\n * @param[in]  image      Image object\n *\n * @return                Image format as described by sp_imageformat\n */\nSP_LIBEXPORT(sp_imageformat) sp_image_format(sp_image *image);\n\n/**\n* Get image data\n*\n* @param[in]  image      Image object\n* @param[out] data_size  Size of raw image data\n*\n* @return                Pointer to raw image data\n*/\n\nSP_LIBEXPORT(const void *) sp_image_data(sp_image *image, size_t *data_size);\n\n/**\n * Get image ID\n *\n * @param[in]  image      Image object\n *\n * @return                Image ID\n */\nSP_LIBEXPORT(const byte *) sp_image_image_id(sp_image *image);\n\n\n/**\n * Increase the reference count of an image\n *\n * @param[in]   image     The image object\n * @return                One of the following errors, from ::sp_error\n *                        SP_ERROR_OK\n */\nSP_LIBEXPORT(sp_error) sp_image_add_ref(sp_image *image);\n\n/**\n * Decrease the reference count of an image\n *\n * @param[in]   image     The image object\n * @return                One of the following errors, from ::sp_error\n *                        SP_ERROR_OK\n */\nSP_LIBEXPORT(sp_error) sp_image_release(sp_image *image);\n\n/** @} */\n\n\n\n/**\n * @defgroup search Search subsystem\n * @{\n */\n\n/**\n * The type of a callback used in sp_search_create()\n *\n * When this callback is called, the sp_track_is_loaded(), sp_album_is_loaded(),\n * and sp_artist_is_loaded() functions will return non-zero for the objects\n * contained in the search result.\n *\n * @param[in]   result          The same pointer returned by sp_search_create()\n * @param[in]   userdata        The opaque pointer given to sp_search_create()\n */\ntypedef void SP_CALLCONV search_complete_cb(sp_search *result, void *userdata);\n\n/**\n * Create a search object from the given query\n *\n * @param[in]  session    Session\n * @param[in]  query      Query search string, e.g. 'The Rolling Stones' or 'album:\"The Black Album\"'\n * @param[in]  track_offset     The offset among the tracks of the result\n * @param[in]  track_count      The number of tracks to ask for\n * @param[in]  album_offset     The offset among the albums of the result\n * @param[in]  album_count      The number of albums to ask for\n * @param[in]  artist_offset    The offset among the artists of the result\n * @param[in]  artist_count     The number of artists to ask for\n * @param[in]  playlist_offset  The offset among the playlists of the result\n * @param[in]  playlist_count   The number of playlists to ask for\n * @param[in]  search_type      Type of search, can be used for suggest searches\n * @param[in]  callback   Callback that will be called once the search operation is complete. Pass NULL if you are not interested in this event.\n * @param[in]  userdata   Opaque pointer passed to \\p callback\n *\n * @return                Pointer to a search object. To free the object, use sp_search_release()\n */\nSP_LIBEXPORT(sp_search *) sp_search_create(sp_session *session, const char *query, int track_offset, int track_count, int album_offset, int album_count, int artist_offset, int artist_count, int playlist_offset, int playlist_count, sp_search_type search_type, search_complete_cb *callback, void *userdata);\n\n/**\n * Get load status for the specified search. Before it is loaded, it will behave as an empty search result.\n *\n * @param[in]  search   Search object\n *\n * @return              True if search is loaded, otherwise false\n */\nSP_LIBEXPORT(bool) sp_search_is_loaded(sp_search *search);\n\n/**\n* Check if search returned an error code.\n*\n* @param[in]   search     Search object\n*\n* @return                 One of the following errors, from ::sp_error\n*                         SP_ERROR_OK\n*                         SP_ERROR_IS_LOADING\n*                         SP_ERROR_OTHER_PERMANENT\n*                         SP_ERROR_OTHER_TRANSIENT\n*/\nSP_LIBEXPORT(sp_error) sp_search_error(sp_search *search);\n\n/**\n * Get the number of tracks for the specified search\n *\n * @param[in]  search   Search object\n *\n * @return              The number of tracks for the specified search\n */\nSP_LIBEXPORT(int) sp_search_num_tracks(sp_search *search);\n\n/**\n * Return the track at the given index in the given search object\n *\n * @param[in]  search     Search object\n * @param[in]  index      Index of the wanted track. Should be in the interval [0, sp_search_num_tracks() - 1]\n *\n * @return                The track at the given index in the given search object\n */\nSP_LIBEXPORT(sp_track *) sp_search_track(sp_search *search, int index);\n\n/**\n * Get the number of albums for the specified search\n *\n * @param[in]  search   Search object\n *\n * @return              The number of albums for the specified search\n */\nSP_LIBEXPORT(int) sp_search_num_albums(sp_search *search);\n\n/**\n * Return the album at the given index in the given search object\n *\n * @param[in]  search     Search object\n * @param[in]  index      Index of the wanted album. Should be in the interval [0, sp_search_num_albums() - 1]\n *\n * @return                The album at the given index in the given search object\n */\nSP_LIBEXPORT(sp_album *) sp_search_album(sp_search *search, int index);\n\n/**\n * Get the number of playlists for the specified search\n *\n * @param[in]  search   Search object\n *\n * @return              The number of playlists for the specified search\n */\nSP_LIBEXPORT(int) sp_search_num_playlists(sp_search *search);\n\n/**\n * Load the playlist at the given index in the given search object\n *\n * @param[in]  search     Search object\n * @param[in]  index      Index of the wanted playlist. Should be in the interval [0, sp_search_num_playlists() - 1]\n *\n * @return                A playlist object. This reference is owned by the caller and should be released with sp_playlist_release()\n */\nSP_LIBEXPORT(sp_playlist *) sp_search_playlist(sp_search *search, int index);\n\n/**\n * Return the playlist at the given index in the given search object\n *\n * @param[in]  search     Search object\n * @param[in]  index      Index of the wanted playlist. Should be in the interval [0, sp_search_num_playlists() - 1]\n *\n * @return                The playlist name at the given index in the given search object\n */\nSP_LIBEXPORT(const char *) sp_search_playlist_name(sp_search *search, int index);\n\n/**\n * Return the uri of a playlist at the given index in the given search object\n *\n * @param[in]  search     Search object\n * @param[in]  index      Index of the wanted playlist. Should be in the interval [0, sp_search_num_playlists() - 1]\n *\n * @return                The playlist uri at the given index in the given search object\n */\nSP_LIBEXPORT(const char *) sp_search_playlist_uri(sp_search *search, int index);\n\n/**\n * Return the image_uri of a playlist at the given index in the given search object\n *\n * @param[in]  search     Search object\n * @param[in]  index      Index of the wanted playlist. Should be in the interval [0, sp_search_num_playlists() - 1]\n *\n * @return                The playlist image_uri at the given index in the given search object\n */\nSP_LIBEXPORT(const char *) sp_search_playlist_image_uri(sp_search *search, int index);\n\n/**\n * Get the number of artists for the specified search\n *\n * @param[in]  search   Search object\n *\n * @return              The number of artists for the specified search\n */\nSP_LIBEXPORT(int) sp_search_num_artists(sp_search *search);\n\n/**\n * Return the artist at the given index in the given search object\n *\n * @param[in]  search     Search object\n * @param[in]  index      Index of the wanted artist. Should be in the interval [0, sp_search_num_artists() - 1]\n *\n * @return                The artist at the given index in the given search object\n */\nSP_LIBEXPORT(sp_artist *) sp_search_artist(sp_search *search, int index);\n\n/**\n * Return the search query for the given search object\n *\n * @param[in]  search     Search object\n *\n * @return                The search query for the given search object\n */\nSP_LIBEXPORT(const char *) sp_search_query(sp_search *search);\n\n/**\n * Return the \"Did you mean\" query for the given search object\n *\n * @param[in]  search     Search object\n *\n * @return                The \"Did you mean\" query for the given search object, or the empty string if no such info is available\n */\nSP_LIBEXPORT(const char *) sp_search_did_you_mean(sp_search *search);\n\n/**\n * Return the total number of tracks for the search query - regardless of the interval requested at creation.\n * If this value is larger than the interval specified at creation of the search object, more search results are available.\n * To fetch these, create a new search object with a new interval.\n *\n * @param[in]  search     Search object\n *\n * @return                The total number of tracks matching the original query\n */\nSP_LIBEXPORT(int) sp_search_total_tracks(sp_search *search);\n\n/**\n * Return the total number of albums for the search query - regardless of the interval requested at creation.\n * If this value is larger than the interval specified at creation of the search object, more search results are available.\n * To fetch these, create a new search object with a new interval.\n *\n * @param[in]  search     Search object\n *\n * @return                The total number of albums matching the original query\n */\nSP_LIBEXPORT(int) sp_search_total_albums(sp_search *search);\n\n/**\n * Return the total number of artists for the search query - regardless of the interval requested at creation.\n * If this value is larger than the interval specified at creation of the search object, more search results are available.\n * To fetch these, create a new search object with a new interval.\n *\n * @param[in]  search     Search object\n *\n * @return                The total number of artists matching the original query\n */\nSP_LIBEXPORT(int) sp_search_total_artists(sp_search *search);\n\n/**\n * Return the total number of playlists for the search query - regardless of the interval requested at creation.\n * If this value is larger than the interval specified at creation of the search object, more search results are available.\n * To fetch these, create a new search object with a new interval.\n *\n * @param[in]  search     Search object\n *\n * @return                The total number of playlists matching the original query\n */\nSP_LIBEXPORT(int) sp_search_total_playlists(sp_search *search);\n\n/**\n * Increase the reference count of a search result\n *\n * @param[in]   search    The search result object\n * @return                One of the following errors, from ::sp_error\n *                        SP_ERROR_OK\n */\nSP_LIBEXPORT(sp_error) sp_search_add_ref(sp_search *search);\n\n/**\n * Decrease the reference count of a search result\n *\n * @param[in]   search    The search result object\n * @return                One of the following errors, from ::sp_error\n *                        SP_ERROR_OK\n */\nSP_LIBEXPORT(sp_error) sp_search_release(sp_search *search);\n\n/** @} */\n\n\n\n\n/**\n * @defgroup playlist Playlist subsystem\n *\n * The playlist subsystem handles playlists and playlist containers (list of playlists).\n *\n * The playlist container functions are always valid, but your playlists are not\n * guaranteed to be loaded until the sp_session_callbacks#logged_in callback has\n * been issued.\n *\n * @{\n */\n\n/**\n * Playlist callbacks\n *\n * Used to get notifications when playlists are updated.\n * If some callbacks should not be of interest, set them to NULL.\n */\ntypedef struct sp_playlist_callbacks {\n\n  /**\n   * Called when one or more tracks have been added to a playlist\n   *\n   * @param[in]  pl         Playlist object\n   * @param[in]  tracks     Array of pointers to track objects\n   * @param[in]  num_tracks Number of entries in \\p tracks\n   * @param[in]  position   Position in the playlist for the first track.\n   * @param[in]  userdata   Userdata passed to sp_playlist_add_callbacks()\n   */\n  void (SP_CALLCONV *tracks_added)(sp_playlist *pl, sp_track * const *tracks, int num_tracks, int position, void *userdata);\n\n  /**\n   * Called when one or more tracks have been removed from a playlist\n   *\n   * @param[in]  pl         Playlist object\n   * @param[in]  tracks     Array of positions representing the tracks that were removed\n   * @param[in]  num_tracks Number of entries in \\p tracks\n   * @param[in]  userdata   Userdata passed to sp_playlist_add_callbacks()\n   */\n  void (SP_CALLCONV *tracks_removed)(sp_playlist *pl, const int *tracks, int num_tracks, void *userdata);\n\n  /**\n   * Called when one or more tracks have been moved within a playlist\n   *\n   * @param[in]  pl         Playlist object\n   * @param[in]  tracks     Array of positions representing the tracks that were moved\n   * @param[in]  num_tracks Number of entries in \\p tracks\n   * @param[in]  position   New position in the playlist for the first track.\n   * @param[in]  userdata   Userdata passed to sp_playlist_add_callbacks()\n   */\n  void (SP_CALLCONV *tracks_moved)(sp_playlist *pl, const int *tracks, int num_tracks, int new_position, void *userdata);\n\n  /**\n   * Called when a playlist has been renamed. sp_playlist_name() can be used to find out the new name\n   *\n   * @param[in]  pl         Playlist object\n   * @param[in]  userdata   Userdata passed to sp_playlist_add_callbacks()\n   */\n  void (SP_CALLCONV *playlist_renamed)(sp_playlist *pl, void *userdata);\n\n  /**\n   * Called when state changed for a playlist.\n   *\n   * There are three states that trigger this callback:\n   * - Collaboration for this playlist has been turned on or off\n   * - The playlist started having pending changes, or all pending changes have now been committed\n   * - The playlist started loading, or finished loading\n   *\n   * @param[in]  pl         Playlist object\n   * @param[in]  userdata   Userdata passed to sp_playlist_add_callbacks()\n   * @sa sp_playlist_is_collaborative\n   * @sa sp_playlist_has_pending_changes\n   * @sa sp_playlist_is_loaded\n   */\n  void (SP_CALLCONV *playlist_state_changed)(sp_playlist *pl, void *userdata);\n\n  /**\n   * Called when a playlist is updating or is done updating\n   *\n   * This is called before and after a series of changes are applied to the\n   * playlist. It allows e.g. the user interface to defer updating until the\n   * entire operation is complete.\n   *\n   * @param[in]  pl         Playlist object\n   * @param[in]  done       True iff the update is completed\n   * @param[in]  userdata   Userdata passed to sp_playlist_add_callbacks()\n   */\n  void (SP_CALLCONV *playlist_update_in_progress)(sp_playlist *pl, bool done, void *userdata);\n\n  /**\n   * Called when metadata for one or more tracks in a playlist has been updated.\n   *\n   * @param[in]  pl         Playlist object\n   * @param[in]  userdata   Userdata passed to sp_playlist_add_callbacks()\n   */\n  void (SP_CALLCONV *playlist_metadata_updated)(sp_playlist *pl, void *userdata);\n\n  /**\n   * Called when create time and/or creator for a playlist entry changes\n   *\n   * @param[in]  pl         Playlist object\n   * @param[in]  position   Position in playlist\n   * @param[in]  user       User object\n   * @param[in]  time       When entry was created, seconds since the unix epoch.\n   * @param[in]  userdata   Userdata passed to sp_playlist_add_callbacks()\n   */\n  void (SP_CALLCONV *track_created_changed)(sp_playlist *pl, int position, sp_user *user, int when, void *userdata);\n\n  /**\n   * Called when seen attribute for a playlist entry changes.\n   *\n   * @param[in]  pl         Playlist object\n   * @param[in]  position   Position in playlist\n   * @param[in]  seen       Set if entry it marked as seen\n   * @param[in]  userdata   Userdata passed to sp_playlist_add_callbacks()\n   */\n  void (SP_CALLCONV *track_seen_changed)(sp_playlist *pl, int position, bool seen, void *userdata);\n\n  /**\n   * Called when playlist description has changed\n   *\n   * @param[in]  pl         Playlist object\n   * @param[in]  desc       New description\n   * @param[in]  userdata   Userdata passed to sp_playlist_add_callbacks()\n   */\n  void (SP_CALLCONV *description_changed)(sp_playlist *pl, const char *desc, void *userdata);\n\n\n  /**\n   * Called when playlist image has changed\n   *\n   * @param[in]  pl         Playlist object\n   * @param[in]  image      New image\n   * @param[in]  userdata   Userdata passed to sp_playlist_add_callbacks()\n   */\n  void (SP_CALLCONV *image_changed)(sp_playlist *pl, const byte *image, void *userdata);\n\n\n  /**\n   * Called when message attribute for a playlist entry changes.\n   *\n   * @param[in]  pl         Playlist object\n   * @param[in]  position   Position in playlist\n   * @param[in]  message    UTF-8 encoded message\n   * @param[in]  userdata   Userdata passed to sp_playlist_add_callbacks()\n   */\n  void (SP_CALLCONV *track_message_changed)(sp_playlist *pl, int position, const char *message, void *userdata);\n\n\n  /**\n   * Called when playlist subscribers changes (count or list of names)\n   *\n   * @param[in]  pl         Playlist object\n   * @param[in]  userdata   Userdata passed to sp_playlist_add_callbacks()\n   */\n  void (SP_CALLCONV *subscribers_changed)(sp_playlist *pl, void *userdata);\n\n} sp_playlist_callbacks;\n\n\n/**\n * Get load status for the specified playlist. If it's false, you have to wait until\n * playlist_state_changed happens, and check again if is_loaded has changed\n *\n * @param[in]  playlist   Playlist object\n *\n * @return                True if playlist is loaded, otherwise false\n */\nSP_LIBEXPORT(bool) sp_playlist_is_loaded(sp_playlist *playlist);\n\n/**\n * Register interest in the given playlist\n *\n * Here is a snippet from \\c jukebox.c:\n * @dontinclude jukebox.c\n * @skipline sp_playlist_add_callbacks\n *\n * @param[in]  playlist   Playlist object\n * @param[in]  callbacks  Callbacks, see #sp_playlist_callbacks\n * @param[in]  userdata   Userdata to be passed to callbacks\n * @sa sp_playlist_remove_callbacks\n *\n */\nSP_LIBEXPORT(sp_error) sp_playlist_add_callbacks(sp_playlist *playlist, sp_playlist_callbacks *callbacks, void *userdata);\n\n/**\n * Unregister interest in the given playlist\n *\n * The combination of (\\p callbacks, \\p userdata) is used to find the entry to be removed\n *\n * Here is a snippet from \\c jukebox.c:\n * @dontinclude jukebox.c\n * @skipline sp_playlist_remove_callbacks\n *\n * @param[in]  playlist   Playlist object\n * @param[in]  callbacks  Callbacks, see #sp_playlist_callbacks\n * @param[in]  userdata   Userdata to be passed to callbacks\n * @sa sp_playlist_add_callbacks\n * @return                One of the following errors, from ::sp_error\n *                        SP_ERROR_OK\n *\n */\nSP_LIBEXPORT(sp_error) sp_playlist_remove_callbacks(sp_playlist *playlist, sp_playlist_callbacks *callbacks, void *userdata);\n\n/**\n * Return number of tracks in the given playlist\n *\n * @param[in]  playlist   Playlist object\n *\n * @return                The number of tracks in the playlist\n */\nSP_LIBEXPORT(int) sp_playlist_num_tracks(sp_playlist *playlist);\n\n/**\n * Return the track at the given index in a playlist\n *\n * @param[in]  playlist   Playlist object\n * @param[in]  index      Index into playlist container. Should be in the interval [0, sp_playlist_num_tracks() - 1]\n *\n * @return                The track at the given index\n */\nSP_LIBEXPORT(sp_track *) sp_playlist_track(sp_playlist *playlist, int index);\n\n/**\n * Return when the given index was added to the playlist\n *\n * @param[in]  playlist   Playlist object\n * @param[in]  index      Index into playlist container. Should be in the interval [0, sp_playlist_num_tracks() - 1]\n *\n * @return                Time, Seconds since unix epoch.\n */\nSP_LIBEXPORT(int) sp_playlist_track_create_time(sp_playlist *playlist, int index);\n\n/**\n * Return user that added the given index in the playlist\n *\n * @param[in]  playlist   Playlist object\n * @param[in]  index      Index into playlist container. Should be in the interval [0, sp_playlist_num_tracks() - 1]\n *\n * @return                User object\n */\nSP_LIBEXPORT(sp_user *) sp_playlist_track_creator(sp_playlist *playlist, int index);\n\n/**\n * Return if a playlist entry is marked as seen or not\n *\n * @param[in]  playlist   Playlist object\n * @param[in]  index      Index into playlist container. Should be in the interval [0, sp_playlist_num_tracks() - 1]\n *\n * @return                Seen state\n */\nSP_LIBEXPORT(bool) sp_playlist_track_seen(sp_playlist *playlist, int index);\n\n/**\n * Set seen status of a playlist entry\n *\n * @param[in]  playlist   Playlist object\n * @param[in]  index      Index into playlist container. Should be in the interval [0, sp_playlist_num_tracks() - 1]\n * @param[in]  seen       Seen status to be set\n *\n * @return     error     One of the following errors, from ::sp_error\n *                       SP_ERROR_OK\n *                       SP_ERROR_INDEX_OUT_OF_RANGE\n */\nSP_LIBEXPORT(sp_error) sp_playlist_track_set_seen(sp_playlist *playlist, int index, bool seen);\n\n/**\n * Return a message attached to a playlist item. Typically used on inbox.\n *\n * @param[in]  playlist   Playlist object\n * @param[in]  index      Index into playlist container. Should be in the interval [0, sp_playlist_num_tracks() - 1]\n *\n * @return                UTF-8 encoded message, or NULL if no message is present\n */\nSP_LIBEXPORT(const char *) sp_playlist_track_message(sp_playlist *playlist, int index);\n\n/**\n * Return name of given playlist\n *\n * @param[in]  playlist   Playlist object\n *\n * @return                The name of the given playlist\n */\nSP_LIBEXPORT(const char *) sp_playlist_name(sp_playlist *playlist);\n\n/**\n * Rename the given playlist\n * The name must not consist of only spaces and it must be shorter than 256 characters.\n *\n * @param[in]  playlist   Playlist object\n * @param[in]  new_name   New name for playlist\n *\n * @return                One of the following errors, from ::sp_error\n *                        SP_ERROR_OK\n *                        SP_ERROR_INVALID_INDATA\n *                        SP_ERROR_PERMISSION_DENIED\n */\nSP_LIBEXPORT(sp_error) sp_playlist_rename(sp_playlist *playlist, const char *new_name);\n\n/**\n * Return a pointer to the user for the given playlist\n *\n * @param[in]  playlist   Playlist object\n *\n * @return                User object\n */\nSP_LIBEXPORT(sp_user *) sp_playlist_owner(sp_playlist *playlist);\n\n/**\n * Return collaborative status for a playlist.\n *\n * A playlist in collaborative state can be modifed by all users, not only the user owning the list\n *\n * @param[in]  playlist   Playlist object\n *\n * @return                true if playlist is collaborative, otherwise false\n */\nSP_LIBEXPORT(bool) sp_playlist_is_collaborative(sp_playlist *playlist);\n\n/**\n * Set collaborative status for a playlist.\n *\n * A playlist in collaborative state can be modified by all users, not only the user owning the list\n *\n * @param[in]  playlist       Playlist object\n * @param[in]  collaborative  True or false\n * @return                    One of the following errors, from ::sp_error\n *                            SP_ERROR_OK\n */\nSP_LIBEXPORT(sp_error) sp_playlist_set_collaborative(sp_playlist *playlist, bool collaborative);\n\n/**\n * Set autolinking state for a playlist.\n *\n * If a playlist is autolinked, unplayable tracks will be made playable\n * by linking them to other Spotify tracks, where possible.\n *\n * @param[in]  playlist       Playlist object\n * @param[in]  link           True or false\n * @return                    One of the following errors, from ::sp_error\n *                            SP_ERROR_OK\n */\nSP_LIBEXPORT(sp_error) sp_playlist_set_autolink_tracks(sp_playlist *playlist, bool link);\n\n\n/**\n * Get description for a playlist\n *\n * @param[in]  playlist       Playlist object\n *\n * @return                    Playlist description or NULL if unset\n *\n */\nSP_LIBEXPORT(const char *) sp_playlist_get_description(sp_playlist *playlist);\n\n\n/**\n * Get description for a playlist\n *\n * @param[in]  playlist       Playlist object\n * @param[out] image          20 byte image id\n\n * @return                    TRUE if playlist has an image, FALSE if not\n *\n */\nSP_LIBEXPORT(bool) sp_playlist_get_image(sp_playlist *playlist, byte image[20]);\n\n\n/**\n * Check if a playlist has pending changes\n *\n * Pending changes are local changes that have not yet been acknowledged by the server.\n *\n * @param[in]  playlist       Playlist object\n *\n * @return                    A flag representing if there are pending changes or not\n */\nSP_LIBEXPORT(bool) sp_playlist_has_pending_changes(sp_playlist *playlist);\n\n/**\n * Add tracks to a playlist\n *\n * @param[in]  playlist       Playlist object\n * @param[in]  tracks         Array of pointer to tracks.\n * @param[in]  num_tracks     Length of \\p tracks array\n * @param[in]  position       Start position in playlist where to insert the tracks\n * @param[in]  session        Your session object\n *\n * @return                One of the following errors, from ::sp_error\n *                        SP_ERROR_OK\n *                        SP_ERROR_INVALID_INDATA - position is > current playlist length\n *                        SP_ERROR_PERMISSION_DENIED\n */\nSP_LIBEXPORT(sp_error) sp_playlist_add_tracks(sp_playlist *playlist, sp_track *const*tracks, int num_tracks, int position, sp_session *session);\n\n/**\n * Remove tracks from a playlist\n *\n * @param[in]  playlist       Playlist object\n * @param[in]  tracks         Array of pointer to track indices.\n *                            A certain track index should be present at most once, e.g. [0, 1, 2] is valid indata,\n *                            whereas [0, 1, 1] is invalid.\n * @param[in]  num_tracks     Length of \\p tracks array\n *\n * @return                    One of the following errors, from ::sp_error\n *                            SP_ERROR_OK\n *                            SP_ERROR_PERMISSION_DENIED\n */\nSP_LIBEXPORT(sp_error) sp_playlist_remove_tracks(sp_playlist *playlist, const int *tracks, int num_tracks);\n\n/**\n * Move tracks in playlist\n *\n * @param[in]  playlist       Playlist object\n * @param[in]  tracks         Array of pointer to track indices to be moved.\n *                            A certain track index should be present at most once, e.g. [0, 1, 2] is valid indata,\n *                            whereas [0, 1, 1] is invalid.\n * @param[in]  num_tracks     Length of \\p tracks array\n * @param[in]  new_position   New position for tracks\n *\n * @return                    One of the following errors, from ::sp_error\n *                            SP_ERROR_OK\n *                            SP_ERROR_INVALID_INDATA - position is > current playlist length\n *                            SP_ERROR_PERMISSION_DENIED\n */\nSP_LIBEXPORT(sp_error) sp_playlist_reorder_tracks(sp_playlist *playlist, const int *tracks, int num_tracks, int new_position);\n\n\n/**\n * Return number of subscribers for a given playlist\n *\n * @param[in]  playlist       Playlist object\n *\n * @return     Number of subscribers\n *\n */\nSP_LIBEXPORT(unsigned int) sp_playlist_num_subscribers(sp_playlist *playlist);\n\n/**\n * Return subscribers for a playlist\n *\n * @param[in]  playlist       Playlist object\n *\n * @return     sp_subscribers struct with array of canonical usernames.\n *             This object should be free'd using sp_playlist_subscribers_free()\n *\n * @note       The count returned for this function may be less than those\n *             returned by sp_playlist_num_subscribers(). Spotify does not\n *             track each user subscribed to a playlist for playlist with\n *             many (>500) subscribers.\n */\nSP_LIBEXPORT(sp_subscribers *) sp_playlist_subscribers(sp_playlist *playlist);\n\n/**\n * Free object returned from sp_playlist_subscribers()\n *\n * @param[in] subscribers   Subscribers object\n * @return                    One of the following errors, from ::sp_error\n *                            SP_ERROR_OK\n */\nSP_LIBEXPORT(sp_error) sp_playlist_subscribers_free(sp_subscribers *subscribers);\n\n/**\n * Ask library to update the subscription count for a playlist\n *\n * When the subscription info has been fetched from the Spotify backend\n * the playlist subscribers_changed() callback will be invoked.\n * In that callback use sp_playlist_num_subscribers() and/or\n * sp_playlist_subscribers() to get information about the subscribers.\n * You can call those two functions anytime you want but the information\n * might not be up to date in such cases\n *\n * @param[in]  session        Session object\n * @param[in]  playlist       Playlist object\n * @return                    One of the following errors, from ::sp_error\n *                            SP_ERROR_OK\n */\nSP_LIBEXPORT(sp_error) sp_playlist_update_subscribers(sp_session *session, sp_playlist *playlist);\n\n/**\n * Return whether a playlist is loaded in RAM (as opposed to only\n * stored on disk)\n *\n * @param[in]  session        Session object\n * @param[in]  playlist       Playlist object\n *\n * @return True iff playlist is in RAM, False otherwise\n *\n * @note       When a playlist is no longer in RAM it will appear empty.\n *             However, libspotify will retain information about the\n *             list metadata  (owner, title, picture, etc) in RAM.\n *             There is one caveat tough: If libspotify has never seen the\n *             playlist before this metadata will also be unset.\n *             In order for libspotify to get the metadata the playlist\n *             needs to be loaded at least once.\n *             In order words, if libspotify starts with an empty playlist\n *             cache and the application has set 'initially_unload_playlists'\n *             config parameter to True all playlists will be empty.\n *             It will not be possible to generate URI's to the playlists\n *             nor extract playlist title until the application calls\n *             sp_playlist_set_in_ram(..., true). So an application\n *             that needs to stay within a low memory profile would need to\n *             cycle thru all new playlists in order to extract metadata.\n *\n *             The easiest way to detect this case is when\n *             sp_playlist_is_in_ram() returns false and\n *             sp_link_create_from_playlist() returns NULL\n */\nSP_LIBEXPORT(bool) sp_playlist_is_in_ram(sp_session *session, sp_playlist *playlist);\n\n/**\n * Return whether a playlist is loaded in RAM (as opposed to only\n * stored on disk)\n *\n * @param[in]  session        Session object\n * @param[in]  playlist       Playlist object\n * @param[in]  in_ram         Controls whether or not to keep the list in RAM\n * @return                    One of the following errors, from ::sp_error\n *                            SP_ERROR_OK\n */\nSP_LIBEXPORT(sp_error) sp_playlist_set_in_ram(sp_session *session, sp_playlist *playlist, bool in_ram);\n\n/**\n * Load an already existing playlist without adding it to a playlistcontainer.\n *\n * @param[in]  session        Session object\n * @param[in]  link           Link object referring to a playlist\n *\n * @return     A playlist. The reference is owned by the caller and should be released with sp_playlist_release()\n *\n */\nSP_LIBEXPORT(sp_playlist *) sp_playlist_create(sp_session *session, sp_link *link);\n\n/**\n * Mark a playlist to be synchronized for offline playback.\n * The playlist must be in the users playlistcontainer\n *\n * @param[in]  session        Session object\n * @param[in]  playlist       Playlist object\n * @param[in]  offline        True iff playlist should be offline, false otherwise\n * @return                    One of the following errors, from ::sp_error\n *                            SP_ERROR_OK\n */\nSP_LIBEXPORT(sp_error) sp_playlist_set_offline_mode(sp_session *session, sp_playlist *playlist, bool offline);\n\n/**\n * Get offline status for a playlist\n *\n * @param[in]  session        Session object\n * @param[in]  playlist       Playlist object\n *\n * @return sp_playlist_offline_status\n *\n * @see When in SP_PLAYLIST_OFFLINE_STATUS_DOWNLOADING mode the\n *      sp_playlist_get_offline_download_completed() method can be used to query\n *      progress of the download\n */\nSP_LIBEXPORT(sp_playlist_offline_status) sp_playlist_get_offline_status(sp_session *session, sp_playlist *playlist);\n\n/**\n * Get download progress for an offline playlist\n *\n * @param[in]  session        Session object\n * @param[in]  playlist       Playlist object\n *\n * @return Value from 0 - 100 that indicates amount of playlist that is downloaded\n * or 0 if the playlist is not in the SP_PLAYLIST_OFFLINE_STATUS_DOWNLOADING mode.\n *\n * @see sp_playlist_offline_status()\n */\nSP_LIBEXPORT(int) sp_playlist_get_offline_download_completed(sp_session *session, sp_playlist *playlist);\n\n/**\n * Increase the reference count of a playlist\n *\n * @param[in]   playlist       The playlist object\n * @return                     One of the following errors, from ::sp_error\n *                             SP_ERROR_OK\n */\nSP_LIBEXPORT(sp_error) sp_playlist_add_ref(sp_playlist *playlist);\n\n/**\n * Decrease the reference count of a playlist\n *\n * @param[in]   playlist       The playlist object\n * @return                     One of the following errors, from ::sp_error\n *                             SP_ERROR_OK\n */\nSP_LIBEXPORT(sp_error) sp_playlist_release(sp_playlist *playlist);\n\n\n/**\n * Playlist container callbacks.\n * If some callbacks should not be of interest, set them to NULL.\n *\n * @see sp_playlistcontainer_add_callbacks\n * @see sp_playlistcontainer_remove_callbacks\n */\ntypedef struct sp_playlistcontainer_callbacks {\n  /**\n   * Called when a new playlist has been added to the playlist container.\n   *\n   * @param[in]  pc         Playlist container\n   * @param[in]  playlist   Playlist object.\n   * @param[in]  position   Position in list\n   * @param[in]  userdata   Userdata as set in sp_playlistcontainer_add_callbacks()\n   */\n  void (SP_CALLCONV *playlist_added)(sp_playlistcontainer *pc, sp_playlist *playlist, int position, void *userdata);\n\n\n  /**\n   * Called when a new playlist has been removed from playlist container\n   *\n   * @param[in]  pc         Playlist container\n   * @param[in]  playlist   Playlist object.\n   * @param[in]  position   Position in list\n   * @param[in]  userdata   Userdata as set in sp_playlistcontainer_add_callbacks()\n   */\n  void (SP_CALLCONV *playlist_removed)(sp_playlistcontainer *pc, sp_playlist *playlist, int position, void *userdata);\n\n\n  /**\n   * Called when a playlist has been moved in the playlist container\n   *\n   * @param[in]  pc         Playlist container\n   * @param[in]  playlist   Playlist object.\n   * @param[in]  position   Previous position in playlist container list\n   * @param[in]  new_position   New position in playlist container list\n   * @param[in]  userdata   Userdata as set in sp_playlistcontainer_add_callbacks()\n   */\n  void (SP_CALLCONV *playlist_moved)(sp_playlistcontainer *pc, sp_playlist *playlist, int position, int new_position, void *userdata);\n\n  /**\n   * Called when the playlist container is loaded\n   *\n   * @param[in]  pc         Playlist container\n   * @param[in]  userdata   Userdata as set in sp_playlistcontainer_add_callbacks()\n   */\n  void (SP_CALLCONV *container_loaded)(sp_playlistcontainer *pc, void *userdata);\n} sp_playlistcontainer_callbacks;\n\n\n/**\n * Register interest in changes to a playlist container\n *\n * @param[in]  pc        Playlist container\n * @param[in]  callbacks Callbacks, see sp_playlistcontainer_callbacks\n * @param[in]  userdata  Opaque value passed to callbacks.\n *\n * @note Every sp_playlistcontainer_add_callbacks() needs to be paired with a corresponding\n *       sp_playlistcontainer_remove_callbacks() that is invoked before releasing the\n *       last reference you own for the container. In other words, you must make sure\n *       to have removed all the callbacks before the container gets destroyed.\n *\n * @sa sp_session_playlistcontainer()\n * @sa sp_playlistcontainer_remove_callbacks\n * @return              One of the following errors, from ::sp_error\n *                      SP_ERROR_OK\n */\nSP_LIBEXPORT(sp_error) sp_playlistcontainer_add_callbacks(sp_playlistcontainer *pc, sp_playlistcontainer_callbacks *callbacks, void *userdata);\n\n\n/**\n * Unregister interest in changes to a playlist container\n *\n * @param[in]  pc        Playlist container\n * @param[in]  callbacks Callbacks, see sp_playlistcontainer_callbacks\n * @param[in]  userdata  Opaque value passed to callbacks.\n *\n * @sa sp_session_playlistcontainer()\n * @sa sp_playlistcontainer_add_callbacks\n * @return              One of the following errors, from ::sp_error\n *                      SP_ERROR_OK\n */\nSP_LIBEXPORT(sp_error) sp_playlistcontainer_remove_callbacks(sp_playlistcontainer *pc, sp_playlistcontainer_callbacks *callbacks, void *userdata);\n\n/**\n * Return the number of playlists in the given playlist container\n *\n * @param[in]  pc        Playlist container\n *\n * @return               Number of playlists, -1 if undefined\n *\n * @sa sp_session_playlistcontainer()\n */\nSP_LIBEXPORT(int) sp_playlistcontainer_num_playlists(sp_playlistcontainer *pc);\n\n/**\n * Return true if the playlistcontainer is fully loaded\n *\n * @param[in]  pc        Playlist container\n *\n * @return               True if container is loaded\n *\n * @note The container_loaded callback will be invoked when this flips to true\n */\nSP_LIBEXPORT(bool) sp_playlistcontainer_is_loaded(sp_playlistcontainer *pc);\n\n/**\n * Return a pointer to the playlist at a specific index\n *\n * @param[in]  pc        Playlist container\n * @param[in]  index     Index in playlist container. Should be in the interval [0, sp_playlistcontainer_num_playlists() - 1]\n *\n * @return               The playlist object\n *\n * @sa sp_session_playlistcontainer()\n */\nSP_LIBEXPORT(sp_playlist *) sp_playlistcontainer_playlist(sp_playlistcontainer *pc, int index);\n\n/**\n * Return the type of the playlist at a @a index\n *\n * @param[in]  pc        Playlist container\n * @param[in]  index     Index in playlist container. Should be in the interval [0, sp_playlistcontainer_num_playlists() - 1]\n *\n * @return               Type of the playlist, @see sp_playlist_type\n *\n * @sa sp_session_playlistcontainer()\n */\nSP_LIBEXPORT(sp_playlist_type) sp_playlistcontainer_playlist_type(sp_playlistcontainer *pc, int index);\n\n/**\n * Return the folder name at @a index\n *\n * @param[in]  pc           Playlist container\n * @param[in]  index        Index in playlist container. Should be in the interval [0, sp_playlistcontainer_num_playlists() - 1].\n *                          Index should point at a start-folder entry, otherwise the empty string is written to buffer.\n * @param[in]  buffer       Pointer to char[] where to store folder name\n * @param[in]  buffer_size  Size of array\n *\n * @return                  One of the following errors, from ::sp_error\n *                          SP_ERROR_OK\n *                          SP_ERROR_INDEX_OUT_OF_RANGE\n *\n * @sa sp_session_playlistcontainer()\n */\nSP_LIBEXPORT(sp_error) sp_playlistcontainer_playlist_folder_name(sp_playlistcontainer *pc, int index, char *buffer, int buffer_size);\n\n/**\n * Return the folder id at @a index\n *\n * @param[in]  pc        Playlist container\n * @param[in]  index     Index in playlist container. Should be in the interval [0, sp_playlistcontainer_num_playlists() - 1]\n *\n * @return               The group ID of the folder. Returns 0 on index out of range, pc being NULL or indexed item not being a folder\n *\n * @sa sp_session_playlistcontainer()\n */\nSP_LIBEXPORT(sp_uint64) sp_playlistcontainer_playlist_folder_id(sp_playlistcontainer *pc, int index);\n\n/**\n * Add an empty playlist at the end of the playlist container.\n * The name must not consist of only spaces and it must be shorter than 256 characters.\n *\n * @param[in]  pc        Playlist container\n * @param[in]  name      Name of new playlist\n *\n * @return               Pointer to the new playlist. Can be NULL if the operation fails.\n */\nSP_LIBEXPORT(sp_playlist *) sp_playlistcontainer_add_new_playlist(sp_playlistcontainer *pc, const char *name);\n\n/**\n * Add an existing playlist at the end of the given playlist container\n *\n * @param[in]  pc        Playlist container\n * @param[in]  link      Link object pointing to a playlist\n *\n * @return               Pointer to the new playlist. Will be NULL if the playlist already exists.\n */\nSP_LIBEXPORT(sp_playlist *) sp_playlistcontainer_add_playlist(sp_playlistcontainer *pc, sp_link *link);\n\n/**\n * Remove playlist at index from the given playlist container\n *\n * @param[in]  pc        Playlist container\n * @param[in]  index     Index of playlist to be removed\n *\n * @return     error     One of the following errors, from ::sp_error\n *                       SP_ERROR_OK\n *                       SP_ERROR_INDEX_OUT_OF_RANGE\n */\nSP_LIBEXPORT(sp_error) sp_playlistcontainer_remove_playlist(sp_playlistcontainer *pc, int index);\n\n/**\n * Move a playlist in the playlist container\n *\n * @param[in]  pc           Playlist container\n * @param[in]  index        Index of playlist to be moved\n * @param[in]  new_position New position for the playlist\n * @param[in]  dry_run      Do not execute the move, only check if it possible\n\n * @return     error        One of the following errors, from ::sp_error\n *                          SP_ERROR_OK\n *                          SP_ERROR_INDEX_OUT_OF_RANGE\n *                          SP_ERROR_INVALID_INDATA - If trying to move a folder into itself\n */\nSP_LIBEXPORT(sp_error) sp_playlistcontainer_move_playlist(sp_playlistcontainer *pc, int index, int new_position, bool dry_run);\n\n\n/**\n * Add a playlist folder\n *\n * @param[in]  pc           Playlist container\n * @param[in]  index        Position of SP_PLAYLIST_TYPE_START_FOLDER entry\n * @param[in]  name         Name of group\n\n * @return     error        One of the following errors, from ::sp_error\n *                          SP_ERROR_OK\n *                          SP_ERROR_INDEX_OUT_OF_RANGE\n *\n * @note This operation will actually create two playlists. One of\n * type SP_PLAYLIST_TYPE_START_FOLDER and immediately following a\n * SP_PLAYLIST_TYPE_END_FOLDER one.\n *\n * To remove a playlist folder both of these must be deleted or the list\n * will be left in an inconsistant state.\n *\n * There is no way to rename a playlist folder. Instead you need to remove\n * the folder and recreate it again.\n */\nSP_LIBEXPORT(sp_error) sp_playlistcontainer_add_folder(sp_playlistcontainer *pc, int index, const char *name);\n\n\n/**\n * Return a pointer to the user object of the owner.\n *\n * @param[in]  pc   Playlist container.\n * @return          The user object or NULL if unknown or none.\n */\nSP_LIBEXPORT(sp_user *) sp_playlistcontainer_owner(sp_playlistcontainer *pc);\n\n\n/**\n * Increase reference count on playlistconatiner object\n *\n * @param[in]  pc   Playlist container.\n * @return          One of the following errors, from ::sp_error\n *                  SP_ERROR_OK\n */\nSP_LIBEXPORT(sp_error) sp_playlistcontainer_add_ref(sp_playlistcontainer *pc);\n\n/**\n * Release reference count on playlistconatiner object\n *\n * @param[in]  pc   Playlist container.\n * @return          One of the following errors, from ::sp_error\n *                  SP_ERROR_OK\n */\nSP_LIBEXPORT(sp_error) sp_playlistcontainer_release(sp_playlistcontainer *pc);\n\n/**\n * Get the number of new tracks in a playlist since the corresponding\n * function sp_playlistcontainer_clear_unseen_tracks() was called. The\n * function always returns the number of new tracks, and fills the\n * \\p tracks array with the new tracks, but not more than specified in\n * \\p num_tracks. The function will return a negative value on failure.\n *\n * @param[in]  pc         Playlist container.\n * @param[in]  playlist   Playlist object.\n * @param[out] tracks     Array of pointer to new tracks (maybe NULL)\n * @param[in]  num_tracks Size of tracks array\n * @return     Returns the number of unseen tracks\n */\nSP_LIBEXPORT(int) sp_playlistcontainer_get_unseen_tracks(sp_playlistcontainer *pc, sp_playlist *playlist, sp_track **tracks, int num_tracks);\n\n/**\n * Clears a playlist from unseen tracks, so that next call to sp_playlistcontainer_get_unseen_tracks() will return 0 until a new track is added to the \\p playslist.\n *\n * @param[in]  pc       Playlist container.\n * @param[in]  playlist   Playlist object.\n * @return     Returns 0 on success and -1 on failure.\n */\nSP_LIBEXPORT(int) sp_playlistcontainer_clear_unseen_tracks(sp_playlistcontainer *pc, sp_playlist *playlist);\n\n/** @} */\n\n\n/**\n * @defgroup user User handling\n * @{\n */\n\n\n/**\n * User relation type\n */\ntypedef enum sp_relation_type {\n  SP_RELATION_TYPE_UNKNOWN = 0,          ///< Not yet known\n  SP_RELATION_TYPE_NONE = 1,             ///< No relation\n  SP_RELATION_TYPE_UNIDIRECTIONAL = 2,   ///< The currently logged in user is following this uer\n  SP_RELATION_TYPE_BIDIRECTIONAL = 3,    ///< Bidirectional friendship established\n} sp_relation_type;\n\n\n\n/**\n * Get a pointer to a string representing the user's canonical username.\n *\n * @param[in]   user         The Spotify user whose canonical username you would like a string representation of\n *\n * @return                   A string representing the canonical username.\n */\nSP_LIBEXPORT(const char *) sp_user_canonical_name(sp_user *user);\n\n/**\n * Get a pointer to a string representing the user's displayable username.\n * If there is no difference between the canonical username and the display name,\n * or if the library does not know about the display name yet, the canonical username will\n * be returned.\n *\n * @param[in]   user         The Spotify user whose displayable username you would like a string representation of\n *\n * @return                   A string\n */\nSP_LIBEXPORT(const char *) sp_user_display_name(sp_user *user);\n\n/**\n * Get load status for a user object. Before it is loaded, only the user's canonical username\n * is known.\n *\n * @param[in]   user         Spotify user object\n *\n * @return                   True if user object is loaded, otherwise false\n */\nSP_LIBEXPORT(bool) sp_user_is_loaded(sp_user *user);\n\n\n/**\n * Increase the reference count of an user\n *\n * @param[in]   user       The user object\n * @return                 One of the following errors, from ::sp_error\n *                         SP_ERROR_OK\n */\nSP_LIBEXPORT(sp_error) sp_user_add_ref(sp_user *user);\n\n/**\n * Decrease the reference count of an user\n *\n * @param[in]   user       The user object\n * @return                 One of the following errors, from ::sp_error\n *                         SP_ERROR_OK\n */\nSP_LIBEXPORT(sp_error) sp_user_release(sp_user *user);\n\n/** @} */\n\n\n/**\n * @defgroup toplist Toplist handling\n * @{\n */\n\n/**\n * Toplist types\n */\ntypedef enum {\n  SP_TOPLIST_TYPE_ARTISTS = 0, ///< Top artists\n  SP_TOPLIST_TYPE_ALBUMS  = 1, ///< Top albums\n  SP_TOPLIST_TYPE_TRACKS  = 2, ///< Top tracks\n} sp_toplisttype;\n\n\n/**\n * Convenience macro to create a toplist region. Toplist regions are ISO 3166-1\n * country codes (in uppercase) encoded in an integer. There are also some reserved\n * codes used to denote non-country regions. See sp_toplistregion\n *\n * Example: SP_TOPLIST_REGION('S', 'E') for Sweden\n */\n#define SP_TOPLIST_REGION(a, b) ((a) << 8 | (b))\n\n/**\n * Special toplist regions\n */\ntypedef enum {\n  SP_TOPLIST_REGION_EVERYWHERE = 0, ///< Global toplist\n  SP_TOPLIST_REGION_USER = 1,       ///< Toplist for a given user\n} sp_toplistregion;\n\n\n/**\n * The type of a callback used in sp_toplistbrowse_create()\n *\n * When the callback is called, the metadata of all tracks belonging to it will have\n * been loaded, so sp_track_is_loaded() will return non-zero. The same goes for the\n * similar toplist data.\n *\n * @param[in]   result          The same pointer returned by sp_toplistbrowse_create()\n * @param[in]   userdata        The opaque pointer given to sp_toplistbrowse_create()\n */\ntypedef void SP_CALLCONV toplistbrowse_complete_cb(sp_toplistbrowse *result, void *userdata);\n\n/**\n * Initiate a request for browsing an toplist\n *\n * The user is responsible for freeing the returned toplist browse using sp_toplistbrowse_release(). This can be done in the callback.\n *\n * @param[in]   session         Session object\n * @param[in]   type            Type of toplist to be browsed. see the sp_toplisttype enum for possible values\n * @param[in]   region          Region. see sp_toplistregion enum. Country specific regions are coded as two chars in an integer.\n *                              Sweden would correspond to 'S' << 8 | 'E'\n * @param[in]   username        If region is SP_TOPLIST_REGION_USER this specifies which user to get toplists for. NULL means the logged in user.\n * @param[in]   callback        Callback to be invoked when browsing has been completed. Pass NULL if you are not interested in this event.\n * @param[in]   userdata        Userdata passed to callback.\n *\n * @return                      Toplist browse object\n *\n * @see ::toplistbrowse_complete_cb\n */\nSP_LIBEXPORT(sp_toplistbrowse *) sp_toplistbrowse_create(sp_session *session, sp_toplisttype type, sp_toplistregion region, const char *username, toplistbrowse_complete_cb *callback, void *userdata);\n\n\n/**\n * Check if an toplist browse request is completed\n *\n * @param[in]   tlb        Toplist browse object\n *\n * @return                 True if browsing is completed, false if not\n */\nSP_LIBEXPORT(bool) sp_toplistbrowse_is_loaded(sp_toplistbrowse *tlb);\n\n/**\n* Check if browsing returned an error code.\n*\n* @param[in]   tlb        Toplist browse object\n*\n* @return                 One of the following errors, from ::sp_error\n*                         SP_ERROR_OK\n*                         SP_ERROR_IS_LOADING\n*                         SP_ERROR_OTHER_PERMANENT\n*                         SP_ERROR_OTHER_TRANSIENT\n*/\nSP_LIBEXPORT(sp_error) sp_toplistbrowse_error(sp_toplistbrowse *tlb);\n\n\n\n/**\n * Increase the reference count of an toplist browse result\n *\n * @param[in]   tlb       The toplist browse result object\n * @return                One of the following errors, from ::sp_error\n *                        SP_ERROR_OK\n */\nSP_LIBEXPORT(sp_error) sp_toplistbrowse_add_ref(sp_toplistbrowse *tlb);\n\n/**\n * Decrease the reference count of an toplist browse result\n *\n * @param[in]   tlb       The toplist browse result object\n * @return                One of the following errors, from ::sp_error\n *                        SP_ERROR_OK\n */\nSP_LIBEXPORT(sp_error) sp_toplistbrowse_release(sp_toplistbrowse *tlb);\n\n/**\n * Given an toplist browse object, return number of artists\n *\n * @param[in]   tlb         Toplist browse object\n *\n * @return                  Number of artists on toplist\n */\nSP_LIBEXPORT(int) sp_toplistbrowse_num_artists(sp_toplistbrowse *tlb);\n\n/**\n * Return the artist at the given index in the given toplist browse object\n *\n * @param[in]  tlb        Toplist object\n * @param[in]  index      Index of the wanted artist. Should be in the interval [0, sp_toplistbrowse_num_artists() - 1]\n *\n * @return                The artist at the given index in the given toplist browse object\n */\nSP_LIBEXPORT(sp_artist *) sp_toplistbrowse_artist(sp_toplistbrowse *tlb, int index);\n\n\n/**\n * Given an toplist browse object, return number of albums\n *\n * @param[in]   tlb         Toplist browse object\n *\n * @return                  Number of albums on toplist\n */\nSP_LIBEXPORT(int) sp_toplistbrowse_num_albums(sp_toplistbrowse *tlb);\n\n\n/**\n * Return the album at the given index in the given toplist browse object\n *\n * @param[in]  tlb        Toplist object\n * @param[in]  index      Index of the wanted album. Should be in the interval [0, sp_toplistbrowse_num_albums() - 1]\n *\n * @return                The album at the given index in the given toplist browse object\n */\nSP_LIBEXPORT(sp_album *) sp_toplistbrowse_album(sp_toplistbrowse *tlb, int index);\n\n\n/**\n * Given an toplist browse object, return number of tracks\n *\n * @param[in]   tlb         Toplist browse object\n *\n * @return                  Number of tracks on toplist\n */\nSP_LIBEXPORT(int) sp_toplistbrowse_num_tracks(sp_toplistbrowse *tlb);\n\n\n/**\n * Return the track at the given index in the given toplist browse object\n *\n * @param[in]  tlb        Toplist object\n * @param[in]  index      Index of the wanted track. Should be in the interval [0, sp_toplistbrowse_num_tracks() - 1]\n *\n * @return                The track at the given index in the given toplist browse object\n */\nSP_LIBEXPORT(sp_track *) sp_toplistbrowse_track(sp_toplistbrowse *tlb, int index);\n\n/**\n * Return the time (in ms) that was spent waiting for the Spotify backend to serve the request\n *\n * @param[in]  tlb        Toplist object\n *\n * @return                -1 if the request was served from the local cache\n *                        If the result is not yet loaded the return value is undefined\n */\nSP_LIBEXPORT(int) sp_toplistbrowse_backend_request_duration(sp_toplistbrowse *tlb);\n\n\n/** @} */\n\n/**\n * @defgroup inbox Inbox subsystem\n * @{\n */\n\n/**\n * The type of a callback used in sp_inbox_post()\n *\n * When this callback is called, the sp_track_is_loaded(), sp_album_is_loaded(),\n * and sp_artist_is_loaded() functions will return non-zero for the objects\n * contained in the search result.\n *\n * @param[in]   result          The same pointer returned by sp_search_create()\n * @param[in]   userdata        The opaque pointer given to sp_search_create()\n */\ntypedef void SP_CALLCONV inboxpost_complete_cb(sp_inbox *result, void *userdata);\n\n/**\n * Add to inbox\n *\n * @param[in]  session    Session object\n * @param[in]  user       Canonical username of recipient\n * @param[in]  tracks     Array of tracks to post\n * @param[in]  num_tracks Number of tracks in \\p tracks\n * @param[in]  message    Message to attach to tracks. UTF-8\n * @param[in]  callback   Callback to be invoked when the request has completed\n * @param[in]  userdata   Userdata passed to callback\n *\n * @return                sp_inbox object if the request has been sent, NULL if request failed to initialize\n */\nSP_LIBEXPORT(sp_inbox *) sp_inbox_post_tracks(sp_session *session, const char *user, sp_track * const *tracks, int num_tracks, const char *message, inboxpost_complete_cb *callback, void *userdata);\n\n\n/**\n* Check if inbox operation returned an error code.\n*\n* @param[in]   inbox      Inbox object\n*\n* @return                 One of the following errors, from ::sp_error\n*                         SP_ERROR_OK\n*                         SP_ERROR_OTHER_TRANSIENT\n*                         SP_ERROR_PERMISSION_DENIED\n*                         SP_ERROR_INVALID_INDATA\n*                         SP_ERROR_INBOX_IS_FULL\n*                         SP_ERROR_NO_SUCH_USER\n*                         SP_ERROR_OTHER_PERMANENT\n*/\nSP_LIBEXPORT(sp_error) sp_inbox_error(sp_inbox *inbox);\n\n/**\n * Increase the reference count of a inbox result\n *\n * @param[in]   inbox    The inbox result object\n * @return               One of the following errors, from ::sp_error\n *                       SP_ERROR_OK\n */\nSP_LIBEXPORT(sp_error) sp_inbox_add_ref(sp_inbox *inbox);\n\n/**\n * Decrease the reference count of a inbox result\n *\n * @param[in]   inbox    The inbox result object\n * @return               One of the following errors, from ::sp_error\n *                       SP_ERROR_OK\n */\nSP_LIBEXPORT(sp_error) sp_inbox_release(sp_inbox *inbox);\n\n/** @} */\n\n/**\n * Return the libspotify build ID\n *\n * This might be useful to have available for display somewhere in your\n * user interface.\n */\nSP_LIBEXPORT(const char *) sp_build_id(void);\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif /* PUBLIC_API_H */\n/**\n * @example browse.c\n *\n * The browse.c example shows how you can use the album, artist, and browse functions.\n * The example also include some rudimentary playlist browsing.\n * It is part of the spshell program\n */\n/**\n * @example search.c\n *\n * The search.c example shows how you can use search functions.\n * It is part of the spshell program\n */\n/**\n * @example toplist.c\n *\n * The toplist.c example shows how you can use toplist functions.\n * It is part of the spshell program\n */\n/**\n * @example jukebox.c\n *\n * The jukebox.c example shows how you can use playback and playlist functions.\n */\n"
  },
  {
    "path": "libspotify/licenses.xhtml",
    "content": "<?xml version             = \"1.0\" encoding=\"utf-8\"?>\n<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\"\n  \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">\n<html xmlns=\"http://www.w3.org/1999/xhtml\" lang=\"en\" xml:lang=\"en\">\n<head>\n  <title>\n    Third-party licenses\n  </title>\n  <style type=\"text/css\" media=\"screen\">\n  body {\n    margin: 20px;\n  }\n  body, td, div, p, li {\n    font-family:helvetica,arial,sans-serif;\n    font-size:13px;\n    line-height:1.3;\n    color:#555;\n  }\n  h1, h2, h3, h4, h5, h6 {\n    font-family: helvetica, arial, sans-serif;\n    font-weight:normal;\n    color: #222;\n    margin: 0;\n    padding: 0;\n    line-height: 1.0;\n  }\n  h1 {\n    font-size:22px;\n    padding: 0px;\n    margin: 0px;\n    color:#222;\n  }\n  h2 {\n    font-size:18px;\n    padding: 0px;\n    margin: 30px 0px 0px;\n    color:#222;\n  }\n  h3 {\n    font-size: 13px;\n    font-weight: bold;\n  }\n  p {\n    margin: 14px 0 14px 0;\n  }\n  a {\n    text-decoration: none;\n  }\n  a:link, a:active {\n    color: #0088CC;\n  }\n  a:visited {\n    color: #406e8d;\n  }\n  a:link:hover, a:active:hover, a:visited:hover {\n    background-color: #e0f2c2;\n    color: #518300;\n    border-color: #999;\n  }\n  h2 a {\n    color: #222 !important;\n  }\n  hr {\n    border: none;\n    border-top: 1px solid #ddd;\n    height: 1px;\n  }\n  ul.toc {\n    list-style: none;\n    padding: 0px;\n    padding-left: 10px;\n  }\n  ul.toc li {\n    padding-left: 0px;\n  }\n  ul {\n    list-style: square;\n    margin: 14px 0px;\n  }\n  li {\n    padding: 0px 0px 4px;\n  }\n  </style>\n</head>\n<body>\n  <div class=\"page-wrapper\">\n    <h1>\n      Third-party licenses\n    </h1>\n    <p>\n      Several fantastic pieces of <a href = \"http://www.gnu.org/philosophy/free-sw.html\">free</a> and <a href=\"http://www.opensource.org/\">open-source</a> software have really helped get <a href=\"http://www.spotify.com/\">Spotify</a> to where it is today. A few require that we include their license agreements within our product. Consider it done. As we enjoy giving credit where it's due, we included the entire list below. This means you can not only see which software we've been using, but the terms of the licenses too. A big thanks from all of us at Spotify to the smart people behind the fantastic programs listed. Rock on!\n    </p>\n    <ul class=\"toc\">\n      <li>\n        <a href=\"#boost\">Boost</a>\n      </li>\n      <li>\n        <a href=\"#expat\">Expat</a>\n      </li>\n      <li>\n        <a href=\"#fastdelegate\">FastDelegate</a>\n      </li>\n      <li>\n        <a href=\"#libogg\">libogg</a>\n      </li>\n      <li>\n        <a href=\"#libvorbis\">libvorbis</a>\n      </li>\n      <li>\n        <a href=\"#tremolo\">Tremolo</a>\n      </li>\n      <li>\n        <a href=\"#tremor\">Tremor</a>\n      </li>\n      <li>\n        <a href=\"#mersennetwister\">Mersenne Twister</a>\n      </li>\n      <li>\n        <a href=\"#zlib\">zlib</a>\n      </li>\n      <li>\n        <a href=\"#curl\">cURL</a>\n      </li>\n      <li>\n        <a href=\"#cares\">c-ares</a>\n      </li>\n    </ul>\n    <hr />\n    <h2><a name=\"boost\" id=\"boost\" href=\"#boost\">\n      Boost\n    </a></h2>\n    <p>\n      <a href=\"http://www.boost.org/\">http://www.boost.org/</a>\n    </p>\n    <p>\n      Boost Software License - Version 1.0 - August 17th, 2003\n    </p>\n    <p>\n      Permission is hereby granted, free of charge, to any person or organization obtaining a copy of the software and accompanying documentation covered by this license (the \"Software\") to use, reproduce, display, distribute, execute, and transmit the Software, and to prepare derivative works of the Software, and to permit third-parties to whom the Software is furnished to do so, all subject to the following:\n    </p>\n    <p>\n      The copyright notices in the Software and this entire statement, including the above license grant, this restriction and the following disclaimer, must be included in all copies of the Software, in whole or in part, and all derivative works of the Software, unless such copies or derivative works are solely in the form of machine-executable object code generated by a source language processor.\n    </p>\n    <p>\n      THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n    </p>\n    <hr />\n    <h2><a name=\"expat\" id=\"expat\" href=\"#expat\">\n      Expat\n    </a></h2>\n    <p>\n      <a href=\"http://www.jclark.com/xml/expat.html\">http://www.jclark.com/xml/expat.html</a>\n    </p>\n    <p>\n      Expat License. Copyright (c) 1998, 1999, 2000 Thai Open Source Software Center Ltd\n    </p>\n    <p>\n      Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the \"Software\"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:\n    </p>\n    <p>\n      The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.\n    </p>\n    <p>\n      THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n    </p>\n    <hr />\n    <h2><a name=\"fastdelegate\" id=\"fastdelegate\" href=\"#fastdelegate\">\n      FastDelegate\n    </a></h2>\n    <p>\n      <a href=\"http://www.codeproject.com/KB/cpp/FastDelegate.aspx\">http://www.codeproject.com/KB/cpp/FastDelegate.aspx</a>\n    </p>\n    <p>\n      THE WORK (AS DEFINED BELOW) IS PROVIDED UNDER THE TERMS OF THIS CODE PROJECT OPEN LICENSE (\"LICENSE\"). THE WORK IS PROTECTED BY COPYRIGHT AND/OR OTHER APPLICABLE LAW. ANY USE OF THE WORK OTHER THAN AS AUTHORIZED UNDER THIS LICENSE OR COPYRIGHT LAW IS PROHIBITED.\n    </p>\n    <p>\n      BY EXERCISING ANY RIGHTS TO THE WORK PROVIDED HEREIN, YOU ACCEPT AND AGREE TO BE BOUND BY THE TERMS OF THIS LICENSE. THE AUTHOR GRANTS YOU THE RIGHTS CONTAINED HEREIN IN CONSIDERATION OF YOUR ACCEPTANCE OF SUCH TERMS AND CONDITIONS. IF YOU DO NOT AGREE TO ACCEPT AND BE BOUND BY THE TERMS OF THIS LICENSE, YOU CANNOT MAKE ANY USE OF THE WORK.\n    </p>\n    <ol>\n      <li>\n        Definitions.\n        <ol type=\"a\">\n          <li>\n            \"Articles\" means, collectively, all articles written by Author which describes how the Source Code and Executable Files for the Work may be used by a user.\n          </li>\n          <li>\n            \"Author\" means the individual or entity that offers the Work under the terms of this License.\n          </li>\n          <li>\n            \"Derivative Work\" means a work based upon the Work or upon the Work and other pre-existing works.\n          </li>\n          <li>\n            \"Executable Files\" refer to the executables, binary files, configuration and any required data files included in the Work.\n          </li>\n          <li>\n            \"Publisher\" means the provider of the website, magazine, CD-ROM, DVD or other medium from or by which the Work is obtained by You.\n          </li>\n          <li>\n            \"Source Code\" refers to the collection of source code and configuration files used to create the Executable Files.\n          </li>\n          <li>\n            \"Standard Version\" refers to such a Work if it has not been modified, or has been modified in accordance with the consent of the Author, such consent being in the full discretion of the Author.\n          </li>\n          <li>\n            \"Work\" refers to the collection of files distributed by the Publisher, including the Source Code, Executable Files, binaries, data files, documentation, whitepapers and the Articles.\n          </li>\n          <li>\n            \"You\" is you, an individual or entity wishing to use the Work and exercise your rights under this License.\n          </li>\n        </ol>\n      </li>\n      <li>\n        Fair Use/Fair Use Rights. Nothing in this License is intended to reduce, limit, or restrict any rights arising from fair use, fair dealing, first sale or other limitations on the exclusive rights of the copyright owner under copyright law or other applicable laws.\n      </li>\n      <li>\n        License Grant. Subject to the terms and conditions of this License, the Author hereby grants You a worldwide, royalty-free, non-exclusive, perpetual (for the duration of the applicable copyright) license to exercise the rights in the Work as stated below:\n        <ol type=\"a\">\n          <li>\n            You may use the standard version of the Source Code or Executable Files in Your own applications.\n          </li>\n          <li>\n            You may apply bug fixes, portability fixes and other modifications obtained from the Public Domain or from the Author. A Work modified in such a way shall still be considered the standard version and will be subject to this License.\n          </li>\n          <li>\n            You may otherwise modify Your copy of this Work (excluding the Articles) in any way to create a Derivative Work, provided that You insert a prominent notice in each changed file stating how, when and where You changed that file.\n          </li>\n          <li>\n            You may distribute the standard version of the Executable Files and Source Code or Derivative Work in aggregate with other (possibly commercial) programs as part of a larger (possibly commercial) software distribution.\n          </li>\n          <li>\n            The Articles discussing the Work published in any form by the author may not be distributed or republished without the Author's consent. The author retains copyright to any such Articles. You may use the Executable Files and Source Code pursuant to this License but you may not repost or republish or otherwise distribute or make available the Articles, without the prior written consent of the Author.\n          </li>\n        </ol>\n        Any subroutines or modules supplied by You and linked into the Source Code or Executable Files this Work shall not be considered part of this Work and will not be subject to the terms of this License.\n      </li>\n      <li>\n        Patent License. Subject to the terms and conditions of this License, each Author hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, import, and otherwise transfer the Work.\n      </li>\n      <li>\n        Restrictions. The license granted in Section 3 above is expressly made subject to and limited by the following restrictions:\n        <ol type=\"a\">\n          <li>\n            You agree not to remove any of the original copyright, patent, trademark, and attribution notices and associated disclaimers that may appear in the Source Code or Executable Files.\n          </li>\n          <li>\n            You agree not to advertise or in any way imply that this Work is a product of Your own.\n          </li>\n          <li>\n            The name of the Author may not be used to endorse or promote products derived from the Work without the prior written consent of the Author.\n          </li>\n          <li>\n            You agree not to sell, lease, or rent any part of the Work. This does not restrict you from including the Work or any part of the Work inside a larger software distribution that itself is being sold. The Work by itself, though, cannot be sold, leased or rented.\n          </li>\n          <li>\n            You may distribute the Executable Files and Source Code only under the terms of this License, and You must include a copy of, or the Uniform Resource Identifier for, this License with every copy of the Executable Files or Source Code You distribute and ensure that anyone receiving such Executable Files and Source Code agrees that the terms of this License apply to such Executable Files and/or Source Code. You may not offer or impose any terms on the Work that alter or restrict the terms of this License or the recipients' exercise of the rights granted hereunder. You may not sublicense the Work. You must keep intact all notices that refer to this License and to the disclaimer of warranties. You may not distribute the Executable Files or Source Code with any technological measures that control access or use of the Work in a manner inconsistent with the terms of this License.\n          </li>\n          <li>\n            You agree not to use the Work for illegal, immoral or improper purposes, or on pages containing illegal, immoral or improper material. The Work is subject to applicable export laws. You agree to comply with all such laws and regulations that may apply to the Work after Your receipt of the Work.\n          </li>\n        </ol>\n      </li>\n      <li>\n        Representations, Warranties and Disclaimer. THIS WORK IS PROVIDED \"AS IS\", \"WHERE IS\" AND \"AS AVAILABLE\", WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES OR CONDITIONS OR GUARANTEES. YOU, THE USER, ASSUME ALL RISK IN ITS USE, INCLUDING COPYRIGHT INFRINGEMENT, PATENT INFRINGEMENT, SUITABILITY, ETC. AUTHOR EXPRESSLY DISCLAIMS ALL EXPRESS, IMPLIED OR STATUTORY WARRANTIES OR CONDITIONS, INCLUDING WITHOUT LIMITATION, WARRANTIES OR CONDITIONS OF MERCHANTABILITY, MERCHANTABLE QUALITY OR FITNESS FOR A PARTICULAR PURPOSE, OR ANY WARRANTY OF TITLE OR NON-INFRINGEMENT, OR THAT THE WORK (OR ANY PORTION THEREOF) IS CORRECT, USEFUL, BUG-FREE OR FREE OF VIRUSES. YOU MUST PASS THIS DISCLAIMER ON WHENEVER YOU DISTRIBUTE THE WORK OR DERIVATIVE WORKS.\n      </li>\n      <li>\n        Indemnity. You agree to defend, indemnify and hold harmless the Author and the Publisher from and against any claims, suits, losses, damages, liabilities, costs, and expenses (including reasonable legal or attorneys’ fees) resulting from or relating to any use of the Work by You.\n      </li>\n      <li>\n        Limitation on Liability. EXCEPT TO THE EXTENT REQUIRED BY APPLICABLE LAW, IN NO EVENT WILL THE AUTHOR OR THE PUBLISHER BE LIABLE TO YOU ON ANY LEGAL THEORY FOR ANY SPECIAL, INCIDENTAL, CONSEQUENTIAL, PUNITIVE OR EXEMPLARY DAMAGES ARISING OUT OF THIS LICENSE OR THE USE OF THE WORK OR OTHERWISE, EVEN IF THE AUTHOR OR THE PUBLISHER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.\n      </li>\n      <li>\n        Termination.\n        <ol type=\"a\">\n          <li>\n            This License and the rights granted hereunder will terminate automatically upon any breach by You of any term of this License. Individuals or entities who have received Derivative Works from You under this License, however, will not have their licenses terminated provided such individuals or entities remain in full compliance with those licenses. Sections 1, 2, 6, 7, 8, 9, 10 and 11 will survive any termination of this License.\n          </li>\n          <li>\n            If You bring a copyright, trademark, patent or any other infringement claim against any contributor over infringements You claim are made by the Work, your License from such contributor to the Work ends automatically.\n          </li>\n          <li>\n            Subject to the above terms and conditions, this License is perpetual (for the duration of the applicable copyright in the Work). Notwithstanding the above, the Author reserves the right to release the Work under different license terms or to stop distributing the Work at any time; provided, however that any such election will not serve to withdraw this License (or any other license that has been, or is required to be, granted under the terms of this License), and this License will continue in full force and effect unless terminated as stated above.\n          </li>\n        </ol>\n      </li>\n      <li>\n        Publisher. The parties hereby confirm that the Publisher shall not, under any circumstances, be responsible for and shall not have any liability in respect of the subject matter of this License. The Publisher makes no warranty whatsoever in connection with the Work and shall not be liable to You or any party on any legal theory for any damages whatsoever, including without limitation any general, special, incidental or consequential damages arising in connection to this license. The Publisher reserves the right to cease making the Work available to You at any time without notice\n      </li>\n      <li>\n        Miscellaneous\n        <ol type=\"a\">\n          <li>\n            This License shall be governed by the laws of the location of the head office of the Author or if the Author is an individual, the laws of location of the principal place of residence of the Author.\n          </li>\n          <li>\n            If any provision of this License is invalid or unenforceable under applicable law, it shall not affect the validity or enforceability of the remainder of the terms of this License, and without further action by the parties to this License, such provision shall be reformed to the minimum extent necessary to make such provision valid and enforceable.\n          </li>\n          <li>\n            No term or provision of this License shall be deemed waived and no breach consented to unless such waiver or consent shall be in writing and signed by the party to be charged with such waiver or consent.\n          </li>\n          <li>\n            This License constitutes the entire agreement between the parties with respect to the Work licensed herein. There are no understandings, agreements or representations with respect to the Work not specified herein. The Author shall not be bound by any additional provisions that may appear in any communication from You. This License may not be modified without the mutual written agreement of the Author and You\n          </li>\n        </ol>\n      </li>\n    </ol>\n    <hr />\n    <h2><a name=\"libogg\" id=\"libogg\" href=\"#libogg\">\n      libogg\n    </a></h2>\n    <p>\n      <a href=\"http://www.xiph.org/ogg/\">http://www.xiph.org/ogg/</a>\n    </p>\n    <p>\n      Copyright (c) 2002, Xiph.org Foundation\n    </p>\n    <p>\n      Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:\n    </p>\n    <ul>\n      <li>\n        Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.\n      </li>\n      <li>\n        Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.\n      </li>\n      <li>\n        Neither the name of the Xiph.org Foundation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.\n      </li>\n    </ul>\n    <p>\n      THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n    </p>\n    <hr />\n    <h2><a name=\"libvorbis\" id=\"libvorbis\" href=\"#libvorbis\">\n      libvorbis\n    </a></h2>\n    <p>\n      <a href=\"http://www.xiph.org/vorbis/\">http://www.xiph.org/vorbis/</a>\n    </p>\n    <p>\n      Copyright (c) 2002-2004 Xiph.org Foundation\n    </p>\n    <p>\n      Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:\n    </p>\n    <ul>\n      <li>\n        Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.\n      </li>\n      <li>\n        Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.\n      </li>\n      <li>\n        Neither the name of the Xiph.org Foundation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.\n      </li>\n    </ul>\n    <p>\n      THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n    </p>\n    <hr />\n    <h2><a name=\"tremolo\" id=\"tremolo\" href=\"#tremolo\">\n      Tremolo\n    </a></h2>\n    <p>\n      <a href=\"http://wss.co.uk/pinknoise/tremolo/\">http://wss.co.uk/pinknoise/tremolo</a>\n    </p>\n    <p>\n      Copyright (C) 2002-2009 Xiph.org Foundation\n      Changes Copyright (C) 2009-2010 Robin Watts for Pinknoise Productions Ltd\n    </p>\n    <p>\n      Redistribution and use in source and binary forms, with or without\n      modification, are permitted provided that the following conditions\n      are met:\n    </p>\n    <p>\n      - Redistributions of source code must retain the above copyright\n      notice, this list of conditions and the following disclaimer.\n    </p>\n    <p>\n      - Redistributions in binary form must reproduce the above copyright\n      notice, this list of conditions and the following disclaimer in the\n      documentation and/or other materials provided with the distribution.\n    </p>\n    <p>\n      - Neither the name of the Xiph.org Foundation nor the names of its\n      contributors may be used to endorse or promote products derived from\n      this software without specific prior written permission.\n    </p>\n    <p>\n      THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n      ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n      LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n      A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION\n      OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n      SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n      LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n      DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n      THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n      (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n      OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n    </p>\n    <hr />\n    <h2><a name=\"tremor\" id=\"tremor\" href=\"#tremor\">\n      Tremor\n    </a></h2>\n    <p>\n      <a href=\"http://wiki.xiph.org/index.php/Tremor\">http://wiki.xiph.org/index.php/Tremor</a>\n    </p>\n    <p>\n      Copyright (c) 2002, Xiph.org Foundation\n    </p>\n    <p>\n      Redistribution and use in source and binary forms, with or without\n      modification, are permitted provided that the following conditions\n      are met:\n    </p>\n    <p>\n      - Redistributions of source code must retain the above copyright\n      notice, this list of conditions and the following disclaimer.\n    </p>\n    <p>\n      - Redistributions in binary form must reproduce the above copyright\n      notice, this list of conditions and the following disclaimer in the\n      documentation and/or other materials provided with the distribution.\n    </p>\n    <p>\n      - Neither the name of the Xiph.org Foundation nor the names of its\n      contributors may be used to endorse or promote products derived from\n      this software without specific prior written permission.\n    </p>\n    <p>\n      THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n      ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n      LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n      A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION\n      OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n      SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n      LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n      DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n      THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n      (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n      OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n    </p>\n    <hr />\n    <h2><a name=\"mersennetwister\" id=\"mersennetwister\" href=\"#mersennetwister\">\n      Mersenne Twister\n    </a></h2>\n    <p>\n      <a href=\"http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/MT2002/CODES/mt19937ar.c\">http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/MT2002/CODES/mt19937ar.c</a>\n    </p>\n    <p>\n      Copyright (C) 1997 - 2002, Makoto Matsumoto and Takuji Nishimura,<br />\n      All rights reserved.\n    </p>\n    <p>\n      Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:\n    </p>\n    <ol>\n      <li>\n        Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.\n      </li>\n      <li>\n        Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.\n      </li>\n      <li>\n        The names of its contributors may not be used to endorse or promote products derived from this software without specific prior written permission.\n      </li>\n    </ol>\n    <p>\n      THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n    </p>\n    <hr />\n    <h2><a name=\"zlib\" id=\"zlib\" href=\"#zlib\">\n      zlib\n    </a></h2>\n    <p>\n      <a href=\"http://www.zlib.net/\">http://www.zlib.net/</a>\n    </p>\n    <p>\n      zlib.h -- interface of the 'zlib' general purpose compression library version 1.2.3, July 18th, 2005\n    </p>\n    <p>\n      Copyright (C) 1995-2004 Jean-loup Gailly and Mark Adler\n    </p>\n    <p>\n      This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software.\n    </p>\n    <p>\n      Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions:\n    </p>\n    <ol>\n      <li>\n        The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.\n      </li>\n      <li>\n        Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.\n      </li>\n      <li>\n        This notice may not be removed or altered from any source distribution.\n      </li>\n    </ol>\n    <p>\n      Jean-loup Gailly <a href=\"mailto:jloup@gzip.org\">jloup@gzip.org</a>, Mark Adler <a href=\"mailto:madler@alumni.caltech.edu\">madler@alumni.caltech.edu</a>\n    </p>\n    <hr />\n    <h2><a name=\"curl\" id=\"curl\" href=\"#curl\">\n      cURL\n    </a></h2>\n    <p>\n      <a href=\"http://curl.haxx.se\">http://curl.haxx.se</a>\n    </p>\n    <p>\n      COPYRIGHT AND PERMISSION NOTICE\n    </p>\n    <p>\n      Copyright (c) 1996 - 2011, Daniel Stenberg, &lt;daniel@haxx.se&gt;.\n    </p>\n    <p>\n      All rights reserved.\n    </p>\n    <p>\n      Permission to use, copy, modify, and distribute this software for any purpose\n      with or without fee is hereby granted, provided that the above copyright\n      notice and this permission notice appear in all copies.\n    </p>\n    <p>\n      THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n      IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n      FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS. IN\n      NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n      DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n      OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE\n      OR OTHER DEALINGS IN THE SOFTWARE.\n    </p>\n    <p>\n      Except as contained in this notice, the name of a copyright holder shall not\n      be used in advertising or otherwise to promote the sale, use or other dealings\n      in this Software without prior written authorization of the\n      copyright holder.\n    </p>\n    <hr />\n    <h2><a name=\"cares\" id=\"cares\" href=\"#cares\">\n      c-ares\n    </a></h2>\n    <p>\n      <a href=\"http://c-ares.haxx.se\">http://c-ares.haxx.se</a>\n    </p>\n    <p>\n      Copyright 1998 by the Massachusetts Institute of Technology.\n    </p>\n    <p>\n      Permission to use, copy, modify, and distribute this software and its\n      documentation for any purpose and without fee is hereby granted, provided that\n      the above copyright notice appear in all copies and that both that copyright\n      notice and this permission notice appear in supporting documentation, and that\n      the name of M.I.T. not be used in advertising or publicity pertaining to\n      distribution of the software without specific, written prior permission.\n      M.I.T. makes no representations about the suitability of this software for any\n     purpose.  It is provided \"as is\" without express or implied warranty.\n    </p>\n </div>\n</body>\n</html>\n"
  },
  {
    "path": "licenses/JSON for Modern C++.txt",
    "content": "MIT License \n\nCopyright (c) 2013-2018 Niels Lohmann\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n"
  },
  {
    "path": "licenses/LibSpotify.txt",
    "content": "For the current terms and conditions, please read:\n\nhttp://developer.spotify.com/en/libspotify/terms-of-use/\n"
  },
  {
    "path": "licenses/PFC.txt",
    "content": "Copyright (C) 2002-2019 Peter Pawlowski\n\nThis software is provided 'as-is', without any express or implied\nwarranty.  In no event will the authors be held liable for any damages\narising from the use of this software.\n\nPermission is granted to anyone to use this software for any purpose,\nincluding commercial applications, and to alter it and redistribute it\nfreely, subject to the following restrictions:\n\n1. The origin of this software must not be misrepresented; you must not\n   claim that you wrote the original software. If you use this software\n   in a product, an acknowledgment in the product documentation would be\n   appreciated but is not required.\n2. Altered source versions must be plainly marked as such, and must not be\n   misrepresented as being the original software.\n3. This notice may not be removed or altered from any source distribution."
  },
  {
    "path": "licenses/WTL.txt",
    "content": "Microsoft Public License (MS-PL)\n\nThis license governs use of the accompanying software. If you use the software, you\naccept this license. If you do not accept the license, do not use the software.\n\n1. Definitions\nThe terms \"reproduce,\" \"reproduction,\" \"derivative works,\" and \"distribution\" have the\nsame meaning here as under U.S. copyright law.\nA \"contribution\" is the original software, or any additions or changes to the software.\nA \"contributor\" is any person that distributes its contribution under this license.\n\"Licensed patents\" are a contributor's patent claims that read directly on its contribution.\n\n2. Grant of Rights\n(A) Copyright Grant- Subject to the terms of this license, including the license conditions and limitations in section 3, each contributor grants you a non-exclusive, worldwide, royalty-free copyright license to reproduce its contribution, prepare derivative works of its contribution, and distribute its contribution or any derivative works that you create.\n(B) Patent Grant- Subject to the terms of this license, including the license conditions and limitations in section 3, each contributor grants you a non-exclusive, worldwide, royalty-free license under its licensed patents to make, have made, use, sell, offer for sale, import, and/or otherwise dispose of its contribution in the software or derivative works of the contribution in the software.\n\n3. Conditions and Limitations\n(A) No Trademark License- This license does not grant you rights to use any contributors' name, logo, or trademarks.\n(B) If you bring a patent claim against any contributor over patents that you claim are infringed by the software, your patent license from such contributor to the software ends automatically.\n(C) If you distribute any portion of the software, you must retain all copyright, patent, trademark, and attribution notices that are present in the software.\n(D) If you distribute any portion of the software in source code form, you may do so only under this license by including a complete copy of this license with your distribution. If you distribute any portion of the software in compiled or object code form, you may only do so under a license that complies with this license.\n(E) The software is licensed \"as-is.\" You bear the risk of using it. The contributors give no express warranties, guarantees or conditions. You may have additional consumer rights under your local laws which this license cannot change. To the extent permitted under your local laws, the contributors exclude the implied warranties of merchantability, fitness for a particular purpose and non-infringement.\n"
  },
  {
    "path": "licenses/fmt.txt",
    "content": "Copyright (c) 2012 - present, Victor Zverovich\n\nPermission is hereby granted, free of charge, to any person obtaining\na copy of this software and associated documentation files (the\n\"Software\"), to deal in the Software without restriction, including\nwithout limitation the rights to use, copy, modify, merge, publish,\ndistribute, sublicense, and/or sell copies of the Software, and to\npermit persons to whom the Software is furnished to do so, subject to\nthe following conditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\nNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE\nLIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION\nOF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION\nWITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n--- Optional exception to the license ---\n\nAs an exception, if, as a result of your compiling your source code, portions\nof this Software are embedded into a machine-executable object form of such\nsource code, you may redistribute such embedded portions in such object form\nwithout including the above copyright and permission notices.\n"
  },
  {
    "path": "licenses/foobar2000 SDK.txt",
    "content": "foobar2000 1.5 SDK\nCopyright (c) 2001-2019, Peter Pawlowski\nAll rights reserved.\n\nRedistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:\n\nRedistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. \nNeither the name of the author nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\nNote that separate less restrictive licenses apply to the included 'pfc' and 'libPPUI' libraries. See license files included in respective folders for details.\n"
  },
  {
    "path": "licenses/range-v3.txt",
    "content": "========================================================\nBoost Software License - Version 1.0 - August 17th, 2003\n========================================================\n\nPermission is hereby granted, free of charge, to any person or organization\nobtaining a copy of the software and accompanying documentation covered by\nthis license (the \"Software\") to use, reproduce, display, distribute,\nexecute, and transmit the Software, and to prepare derivative works of the\nSoftware, and to permit third-parties to whom the Software is furnished to\ndo so, all subject to the following:\n\nThe copyright notices in the Software and this entire statement, including\nthe above license grant, this restriction and the following disclaimer,\nmust be included in all copies of the Software, in whole or in part, and\nall derivative works of the Software, unless such copies or derivative\nworks are solely in the form of machine-executable object code generated by\na source language processor.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT\nSHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE\nFOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,\nARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\nDEALINGS IN THE SOFTWARE.\n\n==============================================================================\nlibc++ License\n==============================================================================\n\nThe libc++ library is dual licensed under both the University of Illinois\n\"BSD-Like\" license and the MIT license.  As a user of this code you may choose\nto use it under either license.  As a contributor, you agree to allow your code\nto be used under both.\n\nFull text of the relevant licenses is included below.\n\n==============================================================================\n\nUniversity of Illinois/NCSA\nOpen Source License\n\nCopyright (c) 2009-2014 by the contributors listed in CREDITS.TXT\nhttp://llvm.org/svn/llvm-project/libcxx/trunk/CREDITS.TXT\n\nAll rights reserved.\n\nDeveloped by:\n\n    LLVM Team\n\n    University of Illinois at Urbana-Champaign\n\n    http://llvm.org\n\nPermission is hereby granted, free of charge, to any person obtaining a copy of\nthis software and associated documentation files (the \"Software\"), to deal with\nthe Software without restriction, including without limitation the rights to\nuse, copy, modify, merge, publish, distribute, sublicense, and/or sell copies\nof the Software, and to permit persons to whom the Software is furnished to do\nso, subject to the following conditions:\n\n    * Redistributions of source code must retain the above copyright notice,\n      this list of conditions and the following disclaimers.\n\n    * Redistributions in binary form must reproduce the above copyright notice,\n      this list of conditions and the following disclaimers in the\n      documentation and/or other materials provided with the distribution.\n\n    * Neither the names of the LLVM Team, University of Illinois at\n      Urbana-Champaign, nor the names of its contributors may be used to\n      endorse or promote products derived from this Software without specific\n      prior written permission.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS\nFOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE\nCONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE\nSOFTWARE.\n\n==============================================================================\n\nCopyright (c) 2009-2014 by the contributors listed in CREDITS.TXT\n  http://llvm.org/svn/llvm-project/libcxx/trunk/CREDITS.TXT\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n\n==============================================================================\nStepanov and McJones, \"Elements of Programming\" license\n==============================================================================\n\n// Copyright (c) 2009 Alexander Stepanov and Paul McJones\n//\n// Permission to use, copy, modify, distribute and sell this software\n// and its documentation for any purpose is hereby granted without\n// fee, provided that the above copyright notice appear in all copies\n// and that both that copyright notice and this permission notice\n// appear in supporting documentation. The authors make no\n// representations about the suitability of this software for any\n// purpose. It is provided \"as is\" without express or implied\n// warranty.\n//\n// Algorithms from\n// Elements of Programming\n// by Alexander Stepanov and Paul McJones\n// Addison-Wesley Professional, 2009\n\n==============================================================================\nSGI C++ Standard Template Library license\n==============================================================================\n\n// Copyright (c) 1994\n// Hewlett-Packard Company\n//\n// Permission to use, copy, modify, distribute and sell this software\n// and its documentation for any purpose is hereby granted without fee,\n// provided that the above copyright notice appear in all copies and\n// that both that copyright notice and this permission notice appear\n// in supporting documentation.  Hewlett-Packard Company makes no\n// representations about the suitability of this software for any\n// purpose.  It is provided \"as is\" without express or implied warranty.\n//\n// Copyright (c) 1996\n// Silicon Graphics Computer Systems, Inc.\n//\n// Permission to use, copy, modify, distribute and sell this software\n// and its documentation for any purpose is hereby granted without fee,\n// provided that the above copyright notice appear in all copies and\n// that both that copyright notice and this permission notice appear\n// in supporting documentation.  Silicon Graphics makes no\n// representations about the suitability of this software for any\n// purpose.  It is provided \"as is\" without express or implied warranty.\n//\n"
  },
  {
    "path": "licenses/ring-span-lite.txt",
    "content": "Boost Software License - Version 1.0 - August 17th, 2003\n\nPermission is hereby granted, free of charge, to any person or organization\nobtaining a copy of the software and accompanying documentation covered by\nthis license (the \"Software\") to use, reproduce, display, distribute,\nexecute, and transmit the Software, and to prepare derivative works of the\nSoftware, and to permit third-parties to whom the Software is furnished to\ndo so, all subject to the following:\n\nThe copyright notices in the Software and this entire statement, including\nthe above license grant, this restriction and the following disclaimer,\nmust be included in all copies of the Software, in whole or in part, and\nall derivative works of the Software, unless such copies or derivative\nworks are solely in the form of machine-executable object code generated by\na source language processor.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT\nSHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE\nFOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,\nARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\nDEALINGS IN THE SOFTWARE.\n"
  },
  {
    "path": "licenses/span-lite.txt",
    "content": "Boost Software License - Version 1.0 - August 17th, 2003\n\nPermission is hereby granted, free of charge, to any person or organization\nobtaining a copy of the software and accompanying documentation covered by\nthis license (the \"Software\") to use, reproduce, display, distribute,\nexecute, and transmit the Software, and to prepare derivative works of the\nSoftware, and to permit third-parties to whom the Software is furnished to\ndo so, all subject to the following:\n\nThe copyright notices in the Software and this entire statement, including\nthe above license grant, this restriction and the following disclaimer,\nmust be included in all copies of the Software, in whole or in part, and\nall derivative works of the Software, unless such copies or derivative\nworks are solely in the form of machine-executable object code generated by\na source language processor.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT\nSHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE\nFOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,\nARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\nDEALINGS IN THE SOFTWARE.\n"
  },
  {
    "path": "props/local_dependencies/libspotify.props",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<Project ToolsVersion=\"4.0\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\n    <ImportGroup Label=\"PropertySheets\">\n    </ImportGroup>\n    <PropertyGroup>\n        <_PropertySheetDisplayName>libspotify</_PropertySheetDisplayName>\n    </PropertyGroup>\n    <PropertyGroup Label=\"UserMacros\">\n        <LibSpotifyDirectory>$(MainDir)libspotify\\</LibSpotifyDirectory>\n        <LibSpotifyLibDirectory>$(LibSpotifyDirectory)lib\\</LibSpotifyLibDirectory>\n        <LibSpotifyIncludeDirectory>$(LibSpotifyDirectory)include\\</LibSpotifyIncludeDirectory>\n        <LibSpotifyDependencies>libspotify.lib</LibSpotifyDependencies>\n    </PropertyGroup>\n    <PropertyGroup>\n        <IncludePath>$(LibSpotifyIncludeDirectory);$(IncludePath)</IncludePath>\n    </PropertyGroup>\n    <ItemDefinitionGroup>\n        <Link>\n            <AdditionalLibraryDirectories>$(LibSpotifyLibDirectory);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>\n            <AdditionalDependencies>$(LibSpotifyDependencies);%(AdditionalDependencies)</AdditionalDependencies>\n        </Link>\n    </ItemDefinitionGroup>\n    <ItemGroup />\n</Project>"
  },
  {
    "path": "props/submodules/fb2k_utils.props",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<Project ToolsVersion=\"4.0\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\n  <ImportGroup Label=\"PropertySheets\">\n  </ImportGroup>\n  <PropertyGroup>\n    <_PropertySheetDisplayName>fb2k_utils</_PropertySheetDisplayName>\n  </PropertyGroup>\n  <PropertyGroup Label=\"UserMacros\">\n    <QwrFb2kUtilsRootDir>$(SolutionDir)..\\submodules\\fb2k_utils\\</QwrFb2kUtilsRootDir>\n    <QwrFb2kUtilsPropsDir>$(QwrFb2kUtilsRootDir)props\\</QwrFb2kUtilsPropsDir>\n  </PropertyGroup>\n  <PropertyGroup>\n    <IncludePath>$(QwrFb2kUtilsRootDir)src\\;$(IncludePath)</IncludePath>\n  </PropertyGroup>\n</Project>"
  },
  {
    "path": "props/submodules/submodules.props",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<Project ToolsVersion=\"4.0\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\n  <ImportGroup Label=\"PropertySheets\">\n  </ImportGroup>\n  <PropertyGroup>\n    <_PropertySheetDisplayName>submodules</_PropertySheetDisplayName>\n  </PropertyGroup>\n  <PropertyGroup Label=\"UserMacros\">\n    <SubmodulesDirectory>$(SolutionDir)..\\submodules\\</SubmodulesDirectory>\n  </PropertyGroup>\n  <PropertyGroup>\n    <IncludePath>$(SubmodulesDirectory);$(IncludePath)</IncludePath>\n  </PropertyGroup>\n</Project>"
  },
  {
    "path": "scripts/README.md",
    "content": "### Main scripts\n- setup.py - Set up everything, so that project can be built.\n- pack_component.py - Pack project binaries to .fb2k-component archive.\n- generate_docs.py - Generate HTML docs from JsDoc docs.\n\n### Auxiliary scripts\n- update_submodules.py - Update submodules to their latest version.\n- update_gh_pages.py - Update gh-pages folder with latest generated content.\n"
  },
  {
    "path": "scripts/call_wrapper.py",
    "content": "#!/usr/bin/env python3\n\nimport traceback\nimport sys\n\nclass SkippedError(Exception):\n     def __init__(self):\n         self.message = \"Skipped error\"\n\ndef final_call_decorator(start_msg: str,\n                         success_msg: str,\n                         failure_msg: str):\n    def f_decorator(f):\n        def wrapper(*args, **kwds):\n            print(start_msg)\n            try:\n                f(*args, **kwds)\n                print(success_msg)\n                sys.exit(0)\n            except SkippedError:\n                print(failure_msg, file=sys.stderr)\n                sys.exit(1)\n            except Exception:\n                traceback.print_exc(file=sys.stderr)\n                print(failure_msg, file=sys.stderr)\n                sys.exit(1)\n\n        return wrapper\n\n    return f_decorator\n"
  },
  {
    "path": "scripts/download_submodules.py",
    "content": "#!/usr/bin/env python3\n\nimport subprocess\nfrom pathlib import Path\n\nimport call_wrapper\n\ndef download_submodule(root_dir, submodule_name):\n    print(f\"Downloading {submodule_name}...\")\n    try:\n        subprocess.check_call(f\"git submodule update --init --depth=10 -- submodules/{submodule_name}\", cwd=root_dir, shell=True)\n    except subprocess.CalledProcessError:\n        try:\n            subprocess.check_call(f\"git submodule update --init --depth=50 -- submodules/{submodule_name}\", cwd=root_dir, shell=True)\n        except subprocess.CalledProcessError:\n            # Shallow copy does not honour default branch config\n            subprocess.check_call(\"git config --add remote.origin.fetch +refs/heads/*:refs/remotes/origin/*\",\n                                  cwd=root_dir/\"submodules\"/submodule_name,\n                                  shell=True)\n            subprocess.check_call(f\"git submodule deinit --force -- submodules/{submodule_name}\", cwd=root_dir, shell=True)\n            subprocess.check_call(f\"git submodule update --init --force -- submodules/{submodule_name}\", cwd=root_dir, shell=True)\n\ndef download():\n    cur_dir = Path(__file__).parent.absolute()\n    root_dir = cur_dir.parent\n\n    subprocess.check_call(\"git submodule sync\", cwd=root_dir, shell=True)\n    subprocess.check_call(\"git submodule foreach git reset --hard\", cwd=root_dir, shell=True)\n    for subdir in [f for f in (root_dir/\"submodules\").iterdir() if f.is_dir()]:\n        download_submodule(root_dir, subdir.name)\n\nif __name__ == '__main__':\n    call_wrapper.final_call_decorator(\n        \"Downloading submodules\",\n        \"Downloading submodules: success\",\n        \"Downloading submodules: failure!\"\n    )(download)()\n"
  },
  {
    "path": "scripts/pack_component.py",
    "content": "#!/usr/bin/env python3\n\nimport argparse\nimport zipfile\nfrom pathlib import Path\nfrom zipfile import ZipFile\n\nimport call_wrapper\n\ndef path_basename_tuple(path):\n    return (path, path.name)\n\ndef zipdir(zip_file, path, arc_path):\n    assert(path.exists() and path.is_dir())\n\n    for file in path.rglob('*'):\n        if (file.name.startswith('.')):\n            # skip `hidden` files\n            continue\n        if (arc_path):\n            file_arc_path = f'{arc_path}/{file.relative_to(path)}'\n        else:\n            file_arc_path = file.relative_to(path)\n        zip_file.write(file, file_arc_path)\n\ndef pack(is_debug = False):\n    cur_dir = Path(__file__).parent.absolute()\n    root_dir = cur_dir.parent\n    result_machine_dir = root_dir/'_result'/('Win32_Debug' if is_debug else 'Win32_Release')\n    assert(result_machine_dir.exists() and result_machine_dir.is_dir())\n\n    output_dir = result_machine_dir\n    output_dir.mkdir(parents=True, exist_ok=True)\n\n    component_zip = output_dir/'foo_spotify.fb2k-component'\n    component_zip.unlink(missing_ok=True)\n\n    with ZipFile(component_zip, 'w', compression=zipfile.ZIP_DEFLATED, compresslevel=9) as z:\n        zipdir(z, root_dir/'licenses', 'licenses')\n\n        z.write(*path_basename_tuple(root_dir/'libspotify'/'lib'/'libspotify.dll'))\n\n        z.write(*path_basename_tuple(root_dir/'LICENSE'))\n        z.write(*path_basename_tuple(root_dir/'CHANGELOG.md'))\n        \n        z.write(*path_basename_tuple(result_machine_dir/'bin'/'foo_spotify.dll'))\n\n        if (is_debug):\n            # Only debug package should have pdbs inside\n            z.write(*path_basename_tuple(result_machine_dir/'dbginfo'/'foo_spotify.pdb'))\n\n    print(f'Generated file: {component_zip}')\n\n    if (not is_debug):\n        # Release pdbs are packed in a separate package\n        pdb_zip = output_dir/'foo_spotify_pdb.zip'\n        if (pdb_zip.exists()):\n            pdb_zip.unlink()\n\n        with ZipFile(pdb_zip, 'w', zipfile.ZIP_DEFLATED) as z:\n            z.write(*path_basename_tuple(result_machine_dir/'dbginfo'/'foo_spotify.pdb'))\n\n        print(f'Generated file: {pdb_zip}')\n\nif __name__ == '__main__':\n    parser = argparse.ArgumentParser(description='Pack component to .fb2k-component')\n    parser.add_argument('--debug', default=False, action='store_true')\n\n    args = parser.parse_args()\n\n    call_wrapper.final_call_decorator(\n        'Packing component',\n        'Packing component: success',\n        'Packing component: failure!'\n    )(\n    pack\n    )(\n        args.debug\n    )\n"
  },
  {
    "path": "scripts/setup.py",
    "content": "#!/usr/bin/env python3\n\nimport argparse\nimport importlib\nimport importlib.util\nimport sys\nimport traceback\nfrom pathlib import Path\nfrom typing import Union\n\nimport call_wrapper\nimport download_submodules\n\nPathLike = Union[str, Path]\n\ndef call_decorator(command_name: str):\n    def f_decorator(f):\n        def wrapper(*args, **kwds):\n            print(f'>> {command_name}: starting')\n            try:\n                f(*args, **kwds)\n                print(f'<< {command_name}: success')\n            except Exception:\n                traceback.print_exc(file=sys.stderr)\n                print(f'<< {command_name}: failure', file=sys.stderr)\n                raise call_wrapper.SkippedError()\n\n        return wrapper\n\n    return f_decorator\n\ndef load_module(script_path):\n    spec = importlib.util.spec_from_file_location(\"module.name\", script_path)\n    mod = importlib.util.module_from_spec(spec)\n    spec.loader.exec_module(mod)\n    return mod\n\ndef setup( skip_submodules_download,\n           skip_submodules_patches ):\n    cur_dir = Path(__file__).parent.absolute()\n    root_dir = cur_dir.parent\n    scripts_path = root_dir/'submodules'/'fb2k_utils'/'scripts'\n\n    if (not skip_submodules_download):\n        call_decorator('Downloading submodules')(download_submodules.download)()\n        if (not skip_submodules_patches):\n            call_decorator('Patching fb2k submodules')(\n                load_module(scripts_path/'patch_fb2k_submodules.py').patch\n            )(\n                root_dir=root_dir\n            )\n\n    call_decorator('Version header generation')(\n        load_module(scripts_path/'generate_version_header.py').generate_header_custom\n    )(\n        repo_dir=root_dir,\n        output_dir=root_dir/'_result'/'AllPlatforms'/'generated',\n        component_prefix='SPTF'\n    )\n    call_decorator('Commit hash header generation')(\n        load_module(scripts_path/'generate_commit_hash_header.py').generate_header_custom\n    )(\n        repo_dir=root_dir,\n        output_dir=root_dir/'_result'/'AllPlatforms'/'generated',\n        component_prefix='SPTF'\n    )\n    call_decorator('SourceLink configuration file generation'\n    )(\n        load_module(scripts_path/'generate_source_link_config.py').generate_config_custom\n    )(\n        repo_dir=root_dir,\n        output_dir=root_dir/'_result'/'AllPlatforms'/'generated',\n        repo='theqwertiest/foo_spotify'\n    )\n    call_decorator('3rd-party notices generation'\n    )(\n        load_module(scripts_path/'generate_third_party.py').generate\n    )(\n        root_dir=root_dir,\n        component_name='Spotify Integration'\n    )\n\nif __name__ == '__main__':\n    parser = argparse.ArgumentParser(description='Setup project')\n    parser.add_argument('--skip_submodules_download', default=False, action='store_true')\n    parser.add_argument('--skip_submodules_patches', default=False, action='store_true')\n\n    args = parser.parse_args()\n\n    call_wrapper.final_call_decorator(\n        'Preparing project repo',\n        'Setup complete!',\n        'Setup failed!'\n    )(\n    setup\n    )(\n        args.skip_submodules_download,\n        args.skip_submodules_patches\n    )\n"
  },
  {
    "path": "scripts/update_gh_pages.py",
    "content": "#!/usr/bin/env python3\n\nimport argparse\nimport shutil\nfrom pathlib import Path\nfrom typing import Union\n\nimport call_wrapper\n\nPathLike = Union[str, Path]\n\ndef update(gh_pages_dir: PathLike):\n    cur_dir = Path(__file__).parent.absolute()\n    root_dir = cur_dir.parent\n\n    gh_pages_dir = Path(gh_pages_dir).resolve()\n    assert(gh_pages_dir.exists() and gh_pages_dir.is_dir())\n\n    ghp_gen_dir = gh_pages_dir/\"assets\"/\"generated_files\"\n    if (ghp_gen_dir.exists()):\n        shutil.rmtree(ghp_gen_dir)\n        ghp_gen_dir.mkdir(parents=True)\n\n    shutil.copytree(root_dir/\"licenses\", ghp_gen_dir/\"licenses\", dirs_exist_ok=True)\n    \n    ghp_inc_dir = gh_pages_dir/\"_includes\"\n    ghp_inc_dir.mkdir(parents=True, exist_ok=True)\n\n    shutil.copy2(root_dir/\"CHANGELOG.md\", gh_pages_dir/\"_includes\"/\"CHANGELOG.md\")\n\nif __name__ == '__main__':\n    cur_dir = Path(__file__).parent.absolute()\n    root_dir = cur_dir.parent\n    gh_pages_dir = root_dir/\"gh-pages\"\n\n    parser = argparse.ArgumentParser(description='Update GitHub Pages content')\n    parser.add_argument('--gh_pages_dir', default=gh_pages_dir)\n\n    args = parser.parse_args()\n\n    call_wrapper.final_call_decorator(\n        \"Updating GitHub Pages content\",\n        \"Updating GitHub Pages content: success\",\n        \"Updating GitHub Pages content: failure!\"\n    )(\n        update\n    )(\n        gh_pages_dir\n    )\n"
  },
  {
    "path": "workspaces/foo_spotify.sln",
    "content": "﻿\nMicrosoft Visual Studio Solution File, Format Version 12.00\n# Visual Studio Version 16\nVisualStudioVersion = 16.0.30225.117\nMinimumVisualStudioVersion = 10.0.40219.1\nProject(\"{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}\") = \"foo_spotify\", \"..\\foo_spotify\\foo_spotify.vcxproj\", \"{FB107A12-DEFC-4782-97FB-EC155B13550C}\"\nEndProject\nProject(\"{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}\") = \"foobar2000_SDK\", \"..\\submodules\\foobar2000\\SDK\\foobar2000_SDK.vcxproj\", \"{E8091321-D79D-4575-86EF-064EA1A4A20D}\"\nEndProject\nProject(\"{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}\") = \"pfc\", \"..\\submodules\\pfc\\pfc.vcxproj\", \"{EBFFFB4E-261D-44D3-B89C-957B31A0BF9C}\"\nEndProject\nProject(\"{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}\") = \"foobar2000_component_client\", \"..\\submodules\\foobar2000\\foobar2000_component_client\\foobar2000_component_client.vcxproj\", \"{71AD2674-065B-48F5-B8B0-E1F9D3892081}\"\nEndProject\nProject(\"{2150E333-8FDC-42A3-9474-1A3956D46DE8}\") = \"Solution Items\", \"Solution Items\", \"{C179572D-BD48-46D8-98D9-3CD4354A1A6C}\"\n\tProjectSection(SolutionItems) = preProject\n\t\t..\\foo_spotify\\.clang-format = ..\\foo_spotify\\.clang-format\n\tEndProjectSection\nEndProject\nProject(\"{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}\") = \"fb2k_utils\", \"..\\submodules\\fb2k_utils\\src\\fb2k_utils.vcxproj\", \"{EE3BF4F9-2014-4CFF-96C8-44CFB85E0571}\"\nEndProject\nProject(\"{2150E333-8FDC-42A3-9474-1A3956D46DE8}\") = \"docs\", \"docs\", \"{6A9AA2D7-2F76-4BD1-80EE-87E4B9DA70DB}\"\n\tProjectSection(SolutionItems) = preProject\n\t\t..\\CHANGELOG.md = ..\\CHANGELOG.md\n\t\t..\\LICENSE = ..\\LICENSE\n\t\t..\\README.md = ..\\README.md\n\tEndProjectSection\nEndProject\nProject(\"{2150E333-8FDC-42A3-9474-1A3956D46DE8}\") = \"submodules\", \"submodules\", \"{096E7B28-E3A6-4685-BA4F-F92FB4091EF2}\"\nEndProject\nGlobal\n\tGlobalSection(SolutionConfigurationPlatforms) = preSolution\n\t\tDebug FB2K|Win32 = Debug FB2K|Win32\n\t\tDebug FB2K|x64 = Debug FB2K|x64\n\t\tDebug|Win32 = Debug|Win32\n\t\tDebug|x64 = Debug|x64\n\t\tRelease FB2K|Win32 = Release FB2K|Win32\n\t\tRelease FB2K|x64 = Release FB2K|x64\n\t\tRelease|Win32 = Release|Win32\n\t\tRelease|x64 = Release|x64\n\tEndGlobalSection\n\tGlobalSection(ProjectConfigurationPlatforms) = postSolution\n\t\t{FB107A12-DEFC-4782-97FB-EC155B13550C}.Debug FB2K|Win32.ActiveCfg = Debug|Win32\n\t\t{FB107A12-DEFC-4782-97FB-EC155B13550C}.Debug FB2K|Win32.Build.0 = Debug|Win32\n\t\t{FB107A12-DEFC-4782-97FB-EC155B13550C}.Debug FB2K|x64.ActiveCfg = Release|Win32\n\t\t{FB107A12-DEFC-4782-97FB-EC155B13550C}.Debug FB2K|x64.Build.0 = Release|Win32\n\t\t{FB107A12-DEFC-4782-97FB-EC155B13550C}.Debug|Win32.ActiveCfg = Debug|Win32\n\t\t{FB107A12-DEFC-4782-97FB-EC155B13550C}.Debug|Win32.Build.0 = Debug|Win32\n\t\t{FB107A12-DEFC-4782-97FB-EC155B13550C}.Debug|x64.ActiveCfg = Debug|Win32\n\t\t{FB107A12-DEFC-4782-97FB-EC155B13550C}.Release FB2K|Win32.ActiveCfg = Release|Win32\n\t\t{FB107A12-DEFC-4782-97FB-EC155B13550C}.Release FB2K|Win32.Build.0 = Release|Win32\n\t\t{FB107A12-DEFC-4782-97FB-EC155B13550C}.Release FB2K|x64.ActiveCfg = Release|Win32\n\t\t{FB107A12-DEFC-4782-97FB-EC155B13550C}.Release FB2K|x64.Build.0 = Release|Win32\n\t\t{FB107A12-DEFC-4782-97FB-EC155B13550C}.Release|Win32.ActiveCfg = Release|Win32\n\t\t{FB107A12-DEFC-4782-97FB-EC155B13550C}.Release|Win32.Build.0 = Release|Win32\n\t\t{FB107A12-DEFC-4782-97FB-EC155B13550C}.Release|x64.ActiveCfg = Release|Win32\n\t\t{E8091321-D79D-4575-86EF-064EA1A4A20D}.Debug FB2K|Win32.ActiveCfg = Debug|Win32\n\t\t{E8091321-D79D-4575-86EF-064EA1A4A20D}.Debug FB2K|Win32.Build.0 = Debug|Win32\n\t\t{E8091321-D79D-4575-86EF-064EA1A4A20D}.Debug FB2K|x64.ActiveCfg = Release|Win32\n\t\t{E8091321-D79D-4575-86EF-064EA1A4A20D}.Debug FB2K|x64.Build.0 = Release|Win32\n\t\t{E8091321-D79D-4575-86EF-064EA1A4A20D}.Debug|Win32.ActiveCfg = Debug|Win32\n\t\t{E8091321-D79D-4575-86EF-064EA1A4A20D}.Debug|Win32.Build.0 = Debug|Win32\n\t\t{E8091321-D79D-4575-86EF-064EA1A4A20D}.Debug|x64.ActiveCfg = Debug|Win32\n\t\t{E8091321-D79D-4575-86EF-064EA1A4A20D}.Release FB2K|Win32.ActiveCfg = Release|Win32\n\t\t{E8091321-D79D-4575-86EF-064EA1A4A20D}.Release FB2K|Win32.Build.0 = Release|Win32\n\t\t{E8091321-D79D-4575-86EF-064EA1A4A20D}.Release FB2K|x64.ActiveCfg = Release|Win32\n\t\t{E8091321-D79D-4575-86EF-064EA1A4A20D}.Release FB2K|x64.Build.0 = Release|Win32\n\t\t{E8091321-D79D-4575-86EF-064EA1A4A20D}.Release|Win32.ActiveCfg = Release|Win32\n\t\t{E8091321-D79D-4575-86EF-064EA1A4A20D}.Release|Win32.Build.0 = Release|Win32\n\t\t{E8091321-D79D-4575-86EF-064EA1A4A20D}.Release|x64.ActiveCfg = Release|Win32\n\t\t{EBFFFB4E-261D-44D3-B89C-957B31A0BF9C}.Debug FB2K|Win32.ActiveCfg = Debug FB2K|Win32\n\t\t{EBFFFB4E-261D-44D3-B89C-957B31A0BF9C}.Debug FB2K|Win32.Build.0 = Debug FB2K|Win32\n\t\t{EBFFFB4E-261D-44D3-B89C-957B31A0BF9C}.Debug FB2K|x64.ActiveCfg = Debug FB2K|x64\n\t\t{EBFFFB4E-261D-44D3-B89C-957B31A0BF9C}.Debug FB2K|x64.Build.0 = Debug FB2K|x64\n\t\t{EBFFFB4E-261D-44D3-B89C-957B31A0BF9C}.Debug|Win32.ActiveCfg = Debug|Win32\n\t\t{EBFFFB4E-261D-44D3-B89C-957B31A0BF9C}.Debug|Win32.Build.0 = Debug|Win32\n\t\t{EBFFFB4E-261D-44D3-B89C-957B31A0BF9C}.Debug|x64.ActiveCfg = Debug|x64\n\t\t{EBFFFB4E-261D-44D3-B89C-957B31A0BF9C}.Debug|x64.Build.0 = Debug|x64\n\t\t{EBFFFB4E-261D-44D3-B89C-957B31A0BF9C}.Release FB2K|Win32.ActiveCfg = Release FB2K|Win32\n\t\t{EBFFFB4E-261D-44D3-B89C-957B31A0BF9C}.Release FB2K|Win32.Build.0 = Release FB2K|Win32\n\t\t{EBFFFB4E-261D-44D3-B89C-957B31A0BF9C}.Release FB2K|x64.ActiveCfg = Release FB2K|x64\n\t\t{EBFFFB4E-261D-44D3-B89C-957B31A0BF9C}.Release FB2K|x64.Build.0 = Release FB2K|x64\n\t\t{EBFFFB4E-261D-44D3-B89C-957B31A0BF9C}.Release|Win32.ActiveCfg = Release|Win32\n\t\t{EBFFFB4E-261D-44D3-B89C-957B31A0BF9C}.Release|Win32.Build.0 = Release|Win32\n\t\t{EBFFFB4E-261D-44D3-B89C-957B31A0BF9C}.Release|x64.ActiveCfg = Release|x64\n\t\t{EBFFFB4E-261D-44D3-B89C-957B31A0BF9C}.Release|x64.Build.0 = Release|x64\n\t\t{71AD2674-065B-48F5-B8B0-E1F9D3892081}.Debug FB2K|Win32.ActiveCfg = Debug|Win32\n\t\t{71AD2674-065B-48F5-B8B0-E1F9D3892081}.Debug FB2K|Win32.Build.0 = Debug|Win32\n\t\t{71AD2674-065B-48F5-B8B0-E1F9D3892081}.Debug FB2K|x64.ActiveCfg = Release|Win32\n\t\t{71AD2674-065B-48F5-B8B0-E1F9D3892081}.Debug FB2K|x64.Build.0 = Release|Win32\n\t\t{71AD2674-065B-48F5-B8B0-E1F9D3892081}.Debug|Win32.ActiveCfg = Debug|Win32\n\t\t{71AD2674-065B-48F5-B8B0-E1F9D3892081}.Debug|Win32.Build.0 = Debug|Win32\n\t\t{71AD2674-065B-48F5-B8B0-E1F9D3892081}.Debug|x64.ActiveCfg = Debug|Win32\n\t\t{71AD2674-065B-48F5-B8B0-E1F9D3892081}.Release FB2K|Win32.ActiveCfg = Release|Win32\n\t\t{71AD2674-065B-48F5-B8B0-E1F9D3892081}.Release FB2K|Win32.Build.0 = Release|Win32\n\t\t{71AD2674-065B-48F5-B8B0-E1F9D3892081}.Release FB2K|x64.ActiveCfg = Release|Win32\n\t\t{71AD2674-065B-48F5-B8B0-E1F9D3892081}.Release FB2K|x64.Build.0 = Release|Win32\n\t\t{71AD2674-065B-48F5-B8B0-E1F9D3892081}.Release|Win32.ActiveCfg = Release|Win32\n\t\t{71AD2674-065B-48F5-B8B0-E1F9D3892081}.Release|Win32.Build.0 = Release|Win32\n\t\t{71AD2674-065B-48F5-B8B0-E1F9D3892081}.Release|x64.ActiveCfg = Release|Win32\n\t\t{EE3BF4F9-2014-4CFF-96C8-44CFB85E0571}.Debug FB2K|Win32.ActiveCfg = Debug|Win32\n\t\t{EE3BF4F9-2014-4CFF-96C8-44CFB85E0571}.Debug FB2K|Win32.Build.0 = Debug|Win32\n\t\t{EE3BF4F9-2014-4CFF-96C8-44CFB85E0571}.Debug FB2K|x64.ActiveCfg = Release|Win32\n\t\t{EE3BF4F9-2014-4CFF-96C8-44CFB85E0571}.Debug FB2K|x64.Build.0 = Release|Win32\n\t\t{EE3BF4F9-2014-4CFF-96C8-44CFB85E0571}.Debug|Win32.ActiveCfg = Debug|Win32\n\t\t{EE3BF4F9-2014-4CFF-96C8-44CFB85E0571}.Debug|Win32.Build.0 = Debug|Win32\n\t\t{EE3BF4F9-2014-4CFF-96C8-44CFB85E0571}.Debug|x64.ActiveCfg = Debug|Win32\n\t\t{EE3BF4F9-2014-4CFF-96C8-44CFB85E0571}.Release FB2K|Win32.ActiveCfg = Release|Win32\n\t\t{EE3BF4F9-2014-4CFF-96C8-44CFB85E0571}.Release FB2K|Win32.Build.0 = Release|Win32\n\t\t{EE3BF4F9-2014-4CFF-96C8-44CFB85E0571}.Release FB2K|x64.ActiveCfg = Release|Win32\n\t\t{EE3BF4F9-2014-4CFF-96C8-44CFB85E0571}.Release FB2K|x64.Build.0 = Release|Win32\n\t\t{EE3BF4F9-2014-4CFF-96C8-44CFB85E0571}.Release|Win32.ActiveCfg = Release|Win32\n\t\t{EE3BF4F9-2014-4CFF-96C8-44CFB85E0571}.Release|Win32.Build.0 = Release|Win32\n\t\t{EE3BF4F9-2014-4CFF-96C8-44CFB85E0571}.Release|x64.ActiveCfg = Release|Win32\n\tEndGlobalSection\n\tGlobalSection(SolutionProperties) = preSolution\n\t\tHideSolutionNode = FALSE\n\tEndGlobalSection\n\tGlobalSection(NestedProjects) = preSolution\n\t\t{E8091321-D79D-4575-86EF-064EA1A4A20D} = {096E7B28-E3A6-4685-BA4F-F92FB4091EF2}\n\t\t{EBFFFB4E-261D-44D3-B89C-957B31A0BF9C} = {096E7B28-E3A6-4685-BA4F-F92FB4091EF2}\n\t\t{71AD2674-065B-48F5-B8B0-E1F9D3892081} = {096E7B28-E3A6-4685-BA4F-F92FB4091EF2}\n\t\t{EE3BF4F9-2014-4CFF-96C8-44CFB85E0571} = {096E7B28-E3A6-4685-BA4F-F92FB4091EF2}\n\tEndGlobalSection\n\tGlobalSection(ExtensibilityGlobals) = postSolution\n\t\tSolutionGuid = {869A994B-3306-4E73-A266-A14CF217581C}\n\tEndGlobalSection\nEndGlobal\n"
  }
]