aboutsummaryrefslogtreecommitdiff
path: root/xbmc/playlists/SmartPlayList.h
blob: 1b027ce67a55392d7fdce7238a40d8fb538cb0cf (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
/*
 *  Copyright (C) 2005-2018 Team Kodi
 *  This file is part of Kodi - https://kodi.tv
 *
 *  SPDX-License-Identifier: GPL-2.0-or-later
 *  See LICENSES/README.md for more information.
 */

#pragma once

#include "dbwrappers/DatabaseQuery.h"
#include "utils/SortUtils.h"
#include "utils/XBMCTinyXML.h"

#include <set>
#include <string>
#include <vector>

class CGUIDialogSmartPlaylistEditor;
class CGUIDialogMediaFilter;
class CURL;
class CVariant;

namespace KODI::PLAYLIST
{

class CSmartPlaylistRule : public CDatabaseQueryRule
{
public:
  CSmartPlaylistRule();
  ~CSmartPlaylistRule() override = default;

  std::string GetLocalizedRule() const;

  static SortBy TranslateOrder(const char *order);
  static std::string TranslateOrder(SortBy order);
  static Field TranslateGroup(const char *group);
  static std::string TranslateGroup(Field group);

  static std::string GetLocalizedField(int field);
  static std::string GetLocalizedGroup(Field group);
  static bool CanGroupMix(Field group);

  static std::vector<Field> GetFields(const std::string &type);
  static std::vector<SortBy> GetOrders(const std::string &type);
  static std::vector<Field> GetGroups(const std::string &type);
  FIELD_TYPE GetFieldType(int field) const override;
  static bool IsFieldBrowseable(int field);

  static bool Validate(const std::string &input, void *data);
  static bool ValidateRating(const std::string &input, void *data);
  static bool ValidateMyRating(const std::string &input, void *data);

protected:
  std::string GetField(int field, const std::string& type) const override;
  int TranslateField(const char *field) const override;
  std::string TranslateField(int field) const override;
  std::string FormatParameter(const std::string &negate,
                              const std::string &oper,
                              const CDatabase &db,
                              const std::string &type) const override;
  std::string FormatWhereClause(const std::string &negate,
                                const std::string& oper,
                                const std::string &param,
                                const CDatabase &db,
                                const std::string &type) const override;
  SEARCH_OPERATOR GetOperator(const std::string &type) const override;
  std::string GetBooleanQuery(const std::string &negate,
                              const std::string &strType) const override;

private:
  std::string GetVideoResolutionQuery(const std::string &parameter) const;
  static std::string FormatLinkQuery(const char* field,
                                     const char* table,
                                     const MediaType& mediaType,
                                     const std::string& mediaField,
                                     const std::string& parameter);
  std::string FormatYearQuery(const std::string& field,
                              const std::string& param,
                              const std::string& parameter) const;
};

class CSmartPlaylistRuleCombination : public CDatabaseQueryRuleCombination
{
public:
  CSmartPlaylistRuleCombination() = default;
  ~CSmartPlaylistRuleCombination() override = default;

  std::string GetWhereClause(const CDatabase &db,
                             const std::string& strType,
                             std::set<std::string> &referencedPlaylists) const;
  void GetVirtualFolders(const std::string& strType,
                         std::vector<std::string> &virtualFolders) const;

  void AddRule(const CSmartPlaylistRule &rule);
};

class CSmartPlaylist : public IDatabaseQueryRuleFactory
{
public:
  CSmartPlaylist();
  ~CSmartPlaylist() override = default;

  bool Load(const CURL& url);
  bool Load(const std::string &path);
  bool Load(const CVariant &obj);
  bool LoadFromXml(const std::string &xml);
  bool LoadFromJson(const std::string &json);
  bool Save(const std::string &path) const;
  bool Save(CVariant &obj, bool full = true) const;
  bool SaveAsJson(std::string &json, bool full = true) const;

  bool OpenAndReadName(const CURL &url);
  bool LoadFromXML(const TiXmlNode *root, const std::string &encoding = "UTF-8");

  void Reset();

  void SetName(const std::string &name);
  void SetType(const std::string &type); // music, video, mixed
  const std::string& GetName() const { return m_playlistName; }
  const std::string& GetType() const { return m_playlistType; }
  bool IsVideoType() const;
  bool IsMusicType() const;

  void SetMatchAllRules(bool matchAll)
  {
    m_ruleCombination.SetType(matchAll ? CSmartPlaylistRuleCombination::CombinationAnd
                                       : CSmartPlaylistRuleCombination::CombinationOr);
  }

  bool GetMatchAllRules() const
  {
    return m_ruleCombination.GetType() == CSmartPlaylistRuleCombination::CombinationAnd;
  }

  void SetLimit(unsigned int limit) { m_limit = limit; }
  unsigned int GetLimit() const { return m_limit; }

  void SetOrder(SortBy order) { m_orderField = order; }
  SortBy GetOrder() const { return m_orderField; }
  void SetOrderAscending(bool orderAscending)
  {
    m_orderDirection = orderAscending ? SortOrderAscending : SortOrderDescending;
  }
  bool GetOrderAscending() const { return m_orderDirection != SortOrderDescending; }
  SortOrder GetOrderDirection() const { return m_orderDirection; }
  void SetOrderAttributes(SortAttribute attributes) { m_orderAttributes = attributes; }
  SortAttribute GetOrderAttributes() const { return m_orderAttributes; }

  void SetGroup(const std::string &group) { m_group = group; }
  const std::string& GetGroup() const { return m_group; }
  void SetGroupMixed(bool mixed) { m_groupMixed = mixed; }
  bool IsGroupMixed() const { return m_groupMixed; }

  /*! \brief get the where clause for a playlist
   We handle playlists inside playlists separately in order to ensure we don't introduce infinite loops
   by playlist A including playlist B which also (perhaps via other playlists) then includes playlistA.

   \param db the database to use to format up results
   \param referencedPlaylists a set of playlists to know when we reach a cycle
   \param needWhere whether we need to prepend the where clause with "WHERE "
   */
  std::string GetWhereClause(const CDatabase &db, std::set<std::string> &referencedPlaylists) const;
  void GetVirtualFolders(std::vector<std::string> &virtualFolders) const;

  std::string GetSaveLocation() const;

  static void GetAvailableFields(const std::string &type, std::vector<std::string> &fieldList);

  static bool IsVideoType(const std::string &type);
  static bool IsMusicType(const std::string &type);
  static bool CheckTypeCompatibility(const std::string &typeLeft, const std::string &typeRight);

  bool IsEmpty(bool ignoreSortAndLimit = true) const;

  // rule creation
  CDatabaseQueryRule *CreateRule() const override;
  CDatabaseQueryRuleCombination *CreateCombination() const override;

private:
  friend class ::CGUIDialogSmartPlaylistEditor;
  friend class ::CGUIDialogMediaFilter;

  const TiXmlNode* readName(const TiXmlNode *root);
  const TiXmlNode* readNameFromPath(const CURL &url);
  const TiXmlNode* readNameFromXml(const std::string &xml);
  bool load(const TiXmlNode *root);

  CSmartPlaylistRuleCombination m_ruleCombination;
  std::string m_playlistName;
  std::string m_playlistType;

  // order information
  unsigned int m_limit;
  SortBy m_orderField;
  SortOrder m_orderDirection;
  SortAttribute m_orderAttributes;
  std::string m_group;
  bool m_groupMixed;

  CXBMCTinyXML m_xmlDoc;
};

} // namespace KODI::PLAYLIST