| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220 | .. default-domain:: cpp.. highlight:: cpplibaria2: C++ library interface to aria2========================================.. Warning::  The API has not been frozen yet. It will be changed on the course of  the development.The libaria2 is a C++ library and offers the core functionality ofaria2. The library takes care of all networking and downloading stuff,so its usage is very straight forward right now. See the followingTutorial section to see how to use API.Tutorial--------This section is a step by step guide to create a program to downloadfiles using libaria2. The complete source is located at*libaria2ex.cc* in *examples* directory.The *libaria2ex* program takes one or more URIs and downloads each ofthem in parallel. The usage is::    Usage: libaria2ex URI [URI...]      Download given URIs in parallel in the current directory.The source code uses C++11 features, so C++11 enabled compiler isrequired. GCC 4.7 works well here.OK, let's look into the source code. First, include aria2.h headerfile::    #include <aria2/aria2.h>Skip to the ``main()`` function. After checking command-linearguments, we initialize libaria2::    aria2::libraryInit();And create aria2 session object::    aria2::Session* session;    // Create default configuration. The libaria2 takes care of signal    // handling.    aria2::SessionConfig config;    // Add event callback    config.downloadEventCallback = downloadEventCallback;    session = aria2::sessionNew(aria2::KeyVals(), config);:type:`Session` ``session`` is an aria2 session object. You need thisobject through out the download process. Please keep in mind that onlyone :type:`Session` object can be allowed per process due to the heavyuse of static objects in aria2 code base.  :type:`Session` object isnot safe for concurrent accesses from multiple threads.  It must beused from one thread at a time.  In general, libaria2 is not entirelythread-safe.  :type:`SessionConfig` ``config`` holds configuration forthe session object. The constructor initializes it with the defaultvalues. In this setup, :member:`SessionConfig::keepRunning` is``false`` which means :func:`run()` returns when all downloads areprocessed, just like aria2c utility without RPC enabled.  And:member:`SessionConfig::useSignalHandler` is ``true``, which meanslibaria2 will setup signal handlers and catches certain signals tohalt download process gracefully. We also setup event handler callbackfunction ``downloadEventCallback``.  It will be called when an eventoccurred such as download is started, completed, etc. In this exampleprogram, we handle 2 events: download completion and error. For eachevent, we print the GID of the download and several otherinformation::  int downloadEventCallback(aria2::Session* session, aria2::DownloadEvent event,			    const aria2::A2Gid& gid, void* userData)  {    switch(event) {    case aria2::EVENT_ON_DOWNLOAD_COMPLETE:      std::cerr << "COMPLETE";      break;    case aria2::EVENT_ON_DOWNLOAD_ERROR:      std::cerr << "ERROR";      break;    default:      return 0;    }    std::cerr << " [" << aria2::gidToHex(gid) << "] ";    ...  }The ``userData`` object is specified by:member:`SessionConfig::userData`. In this example, we don't specifyit, so it is ``nullptr``.The first argument to :func:`sessionNew()` is ``aria2::KeyVals()``.This type is used in API to specify vector of key/value pairs, mostlyrepresenting aria2 options. For example, specify an option``file-allocation`` to ``none``::    aria2::KeyVals options;    options.push_back(std::pair<std::string, std::string> ("file-allocation", "none"));The first argument of :func:`sessionNew()` is analogous to thecommand-line argument to aria2c program. In the example program, weprovide no options, so just pass empty vector.After the creation of session object, let's add downloads given in thecommand-line::    // Add download item to session    for(int i = 1; i < argc; ++i) {      std::vector<std::string> uris = {argv[i]};      aria2::KeyVals options;      rv = aria2::addUri(session, nullptr, uris, options);      if(rv < 0) {	std::cerr << "Failed to add download " << uris[0] << std::endl;      }    }We iterate command-line arguments and add each of them as a separatedownload. :func:`addUri()` can take one or more URIs to downloadseveral sources, just like aria2c does, but in this example, we justgive just one URI. We provide no particular option for the download,so pass the empty vector as options. The second argument of:func:`addUri()` takes a pointer to :type:`A2Gid`. If it is not``NULL``, the function assigns the GID of the new download to it.  Inthis example code, we have no interest for it, so just pass``nullptr``.We have set up everything at this stage. So let's start download.  Toperform the download, call :func:`run()` repeatedly until it returnsthe value other than ``1``::    for(;;) {      rv = aria2::run(session, aria2::RUN_ONCE);      if(rv != 1) {	break;      }      ...    }Here, we call :func:`run()` with :c:macro:`RUN_ONCE`. It means:func:`run()` returns after one event polling and its action handlingor polling timeout (which is approximately 1 second). If :func:`run()`returns ``1``, it means the download is in progress and theapplication must call it again. If it returns ``0``, then no downloadis left (or it is stopped by signal handler or :func:`shutdown()`).If the function catches error, it returns ``-1``.  The good point ofusing :c:macro:`RUN_ONCE` is that the application can use libaria2 APIwhen :func:`run()` returns. In the example program, we print theprogress of the download in every no less than 500 millisecond::    // Print progress information once per 500ms    if(count >= 500) {      start = now;      aria2::GlobalStat gstat = aria2::getGlobalStat(session);      std::cerr << "Overall #Active:" << gstat.numActive                << " #waiting:" << gstat.numWaiting                << " D:" << gstat.downloadSpeed/1024 << "KiB/s"                << " U:"<< gstat.uploadSpeed/1024 << "KiB/s " << std::endl;      std::vector<aria2::A2Gid> gids = aria2::getActiveDownload(session);      for(const auto& gid : gids) {        aria2::DownloadHandle* dh = aria2::getDownloadHandle(session, gid);        if(dh) {          std::cerr << "    [" << aria2::gidToHex(gid) << "] "                    << dh->getCompletedLength() << "/"                    << dh->getTotalLength() << "("                    << (dh->getTotalLength() > 0 ?                        (100*dh->getCompletedLength()/dh->getTotalLength())                        : 0) << "%)"                    << " D:"                    << dh->getDownloadSpeed()/1024 << "KiB/s, U:"                    << dh->getUploadSpeed()/1024 << "KiB/s"                    << std::endl;          aria2::deleteDownloadHandle(dh);        }      }    }We first call :func:`getGlobalStat()` function to get globalstatistics of the downloads. Then, call :func:`getActiveDownload()`function to get the vector of active download's GID. For each GID, weretrieve :class:`DownloadHandle` object using:func:`getDownloadHandle` function and get detailed information.Please don't forget to delete :class:`DownloadHandle` after the useand before the next call of :func:`run()`.  Keep in mind that the lifetime of :class:`DownloadHandle` object is before the next call of:func:`run()` function.After the loop, finalize download calling :func:`sessionFinal()`function and call :func:`libraryDeinit()` to release resources for thelibrary::    rv = aria2::sessionFinal(session);    aria2::libraryDeinit();    return rv;Calling :func:`sessionFinal()` is important because it performspost-download action, including saving sessions and destroys sessionobject. So failing to call this function will lead to lose thedownload progress and memory leak. The :func:`sessionFinal()` returnsthe code defined in :ref:`exit-status`. aria2c program also returnsthe same value as exist status, so do the same in this tiny exampleprogram.See also *libaria2wx.cc* which uses wx GUI component as UI and usebackground thread to run download.API Reference-------------To use the API function, include ``aria2/aria2.h``::    #include <aria2/aria2.h>All enums, types and functions are under ``aria2`` namespace. To linkwith libaria2, use linker flag ``-laria2``... include:: libaria2api
 |