1 /*MT*
2 
3     MediaTomb - http://www.mediatomb.cc/
4 
5     items.cc - this file is part of MediaTomb.
6 
7     Copyright (C) 2005 Gena Batyan <bgeradz@mediatomb.cc>,
8                        Sergey 'Jin' Bostandzhyan <jin@mediatomb.cc>
9 
10     Copyright (C) 2006-2010 Gena Batyan <bgeradz@mediatomb.cc>,
11                             Sergey 'Jin' Bostandzhyan <jin@mediatomb.cc>,
12                             Leonhard Wimmer <leo@mediatomb.cc>
13 
14     MediaTomb is free software; you can redistribute it and/or modify
15     it under the terms of the GNU General Public License version 2
16     as published by the Free Software Foundation.
17 
18     MediaTomb is distributed in the hope that it will be useful,
19     but WITHOUT ANY WARRANTY; without even the implied warranty of
20     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21     GNU General Public License for more details.
22 
23     You should have received a copy of the GNU General Public License
24     version 2 along with MediaTomb; if not, write to the Free Software
25     Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
26 
27     $Id$
28 */
29 
30 /// \file items.cc
31 
32 #include "pages.h" // API
33 
34 #include "cds_objects.h"
35 #include "content/autoscan.h"
36 #include "database/database.h"
37 #include "server.h"
38 #include "upnp_xml.h"
39 
Items(std::shared_ptr<ContentManager> content,std::shared_ptr<UpnpXMLBuilder> xmlBuilder)40 Web::Items::Items(std::shared_ptr<ContentManager> content, std::shared_ptr<UpnpXMLBuilder> xmlBuilder)
41     : WebRequestHandler(std::move(content))
42     , xmlBuilder(std::move(xmlBuilder))
43 {
44 }
45 
46 /// \brief orocess request for item list in ui
process()47 void Web::Items::process()
48 {
49     check_request();
50 
51     int parentID = intParam("parent_id");
52     int start = intParam("start");
53     int count = intParam("count");
54     if (start < 0)
55         throw_std_runtime_error("illegal start parameter");
56     if (count < 0)
57         throw_std_runtime_error("illegal count parameter");
58 
59     // set result options
60     auto root = xmlDoc->document_element();
61     auto items = root.append_child("items");
62     xml2JsonHints->setArrayName(items, "item");
63     xml2JsonHints->setFieldType("title", "string");
64     items.append_attribute("parent_id") = parentID;
65 
66     auto container = database->loadObject(parentID);
67     auto param = BrowseParam(container, BROWSE_DIRECT_CHILDREN | BROWSE_ITEMS);
68     param.setRange(start, count);
69 
70     auto c = container->getClass();
71     if (c == UPNP_CLASS_MUSIC_ALBUM || c == UPNP_CLASS_PLAYLIST_CONTAINER)
72         param.setFlag(BROWSE_TRACK_SORT);
73 
74     // get contents of request
75     auto arr = database->browse(param);
76     items.append_attribute("virtual") = container->isVirtual();
77     items.append_attribute("start") = start;
78     //items.append_attribute("returned") = arr->size();
79     items.append_attribute("total_matches") = param.getTotalMatches();
80 
81     bool protectContainer = false;
82     bool protectItems = false;
83     std::string autoscanMode = "none";
84 
85     auto parentDir = database->getAutoscanDirectory(parentID);
86     int autoscanType = 0;
87     if (parentDir) {
88         autoscanType = parentDir->persistent() ? 2 : 1;
89         autoscanMode = "timed";
90     }
91 
92 #ifdef HAVE_INOTIFY
93     if (config->getBoolOption(CFG_IMPORT_AUTOSCAN_USE_INOTIFY)) {
94         // check for inotify mode
95         int startpoint_id = INVALID_OBJECT_ID;
96         if (autoscanType == 0) {
97             auto pathIDs = database->getPathIDs(parentID);
98             for (int pathId : pathIDs) {
99                 auto pathDir = database->getAutoscanDirectory(pathId);
100                 if (pathDir && pathDir->getRecursive()) {
101                     startpoint_id = pathId;
102                     break;
103                 }
104             }
105         } else {
106             startpoint_id = parentID;
107         }
108 
109         if (startpoint_id != INVALID_OBJECT_ID) {
110             auto startPtDir = database->getAutoscanDirectory(startpoint_id);
111             if (startPtDir && startPtDir->getScanMode() == ScanMode::INotify) {
112                 protectItems = true;
113                 if (autoscanType == 0 || startPtDir->persistent())
114                     protectContainer = true;
115 
116                 autoscanMode = "inotify";
117             }
118         }
119     }
120 #endif
121     items.append_attribute("autoscan_mode") = autoscanMode.c_str();
122     items.append_attribute("autoscan_type") = mapAutoscanType(autoscanType).data();
123     items.append_attribute("protect_container") = protectContainer;
124     items.append_attribute("protect_items") = protectItems;
125 
126     // ouput objects of container
127     for (auto&& arrayObj : arr) {
128         auto item = items.append_child("item");
129         item.append_attribute("id") = arrayObj->getID();
130         item.append_child("title").append_child(pugi::node_pcdata).set_value(arrayObj->getTitle().c_str());
131 
132         auto objItem = std::static_pointer_cast<CdsItem>(arrayObj);
133         std::string res = UpnpXMLBuilder::getFirstResourcePath(objItem);
134         item.append_child("res").append_child(pugi::node_pcdata).set_value(res.c_str());
135 
136         auto [url, artAdded] = xmlBuilder->renderItemImage(server->getVirtualUrl(), objItem);
137         if (artAdded) {
138             item.append_child("image").append_child(pugi::node_pcdata).set_value(url.c_str());
139         }
140     }
141 }
142