Skip to content
This repository
Browse code

Merge pull request #1582 from alcoheca/upnp-cache-notify

Upnp cache notify
  • Loading branch information...
commit 59ca8732710dff84330672a0b3bcb826477b7c50 2 parents 70205b0 + 7e139d5
Alasdair Campbell authored October 11, 2012
4  language/English/strings.po
@@ -8257,7 +8257,9 @@ msgctxt "#20187"
8257 8257
 msgid "UPnP"
8258 8258
 msgstr ""
8259 8259
 
8260  
-#empty string with id 20188
  8260
+msgctxt "#20188"
  8261
+msgid "Announce library updates via UPnP"
  8262
+msgstr ""
8261 8263
 
8262 8264
 msgctxt "#20189"
8263 8265
 msgid "Enable auto scrolling for plot & review"
11  lib/libUPnP/Platinum/Source/Core/PltService.cpp
@@ -460,14 +460,14 @@ PLT_Service::IsSubscribable()
460 460
 |   PLT_Service::SetStateVariable
461 461
 +---------------------------------------------------------------------*/
462 462
 NPT_Result
463  
-PLT_Service::SetStateVariable(const char* name, const char* value)
  463
+PLT_Service::SetStateVariable(const char* name, const char* value, const bool clearonsend /*=false*/)
464 464
 {
465 465
     PLT_StateVariable* stateVariable = NULL;
466 466
     NPT_ContainerFind(m_StateVars, PLT_StateVariableNameFinder(name), stateVariable);
467 467
     if (stateVariable == NULL)
468 468
         return NPT_FAILURE;
469 469
 
470  
-    return stateVariable->SetValue(value);
  470
+    return stateVariable->SetValue(value, clearonsend);
471 471
 }
472 472
 
473 473
 /*----------------------------------------------------------------------
@@ -838,6 +838,13 @@ PLT_Service::NotifyChanged()
838 838
         delete sub;
839 839
     }
840 840
 
  841
+    // some state variables must be cleared immediatly after sending
  842
+    iter = vars_ready.GetFirstItem();
  843
+    while (iter) {
  844
+      PLT_StateVariable* var = *iter;
  845
+      var->OnSendCompleted();
  846
+      ++iter;
  847
+    }
841 848
     return NPT_SUCCESS;
842 849
 }
843 850
 
3  lib/libUPnP/Platinum/Source/Core/PltService.h
@@ -216,8 +216,9 @@ class PLT_Service
216 216
      when necessary.
217 217
      @param name state variable name
218 218
      @param value new State Variable value.
  219
+     @param clearonsend whether the State Variable should clear immediatly in ::OnSendingCompleted
219 220
      */
220  
-    NPT_Result SetStateVariable(const char* name, const char* value);
  221
+    NPT_Result SetStateVariable(const char* name, const char* value, const bool clearonsend = false);
221 222
     
222 223
     /**
223 224
      Certain state variables notifications must not be sent faster than a certain 
16  lib/libUPnP/Platinum/Source/Core/PltStateVariable.cpp
@@ -48,7 +48,8 @@ NPT_SET_LOCAL_LOGGER("platinum.core.statevariable")
48 48
 PLT_StateVariable::PLT_StateVariable(PLT_Service* service) : 
49 49
     m_Service(service), 
50 50
     m_AllowedValueRange(NULL),
51  
-    m_IsSendingEventsIndirectly(true)
  51
+    m_IsSendingEventsIndirectly(true),
  52
+    m_ShouldClearOnSend(false)
52 53
 {
53 54
 }
54 55
 
@@ -145,7 +146,7 @@ PLT_StateVariable::SetRate(NPT_TimeInterval rate)
145 146
 |   PLT_StateVariable::SetValue
146 147
 +---------------------------------------------------------------------*/
147 148
 NPT_Result
148  
-PLT_StateVariable::SetValue(const char* value)
  149
+PLT_StateVariable::SetValue(const char* value, const bool clearonsend /*=false*/)
149 150
 {
150 151
     if (value == NULL) {
151 152
         return NPT_FAILURE;
@@ -159,6 +160,7 @@ PLT_StateVariable::SetValue(const char* value)
159 160
         }
160 161
 
161 162
         m_Value = value;
  163
+        m_ShouldClearOnSend = clearonsend;
162 164
         m_Service->AddChanged(this); 
163 165
     }
164 166
 
@@ -183,6 +185,16 @@ PLT_StateVariable::IsReadyToPublish()
183 185
 }
184 186
 
185 187
 /*----------------------------------------------------------------------
  188
+|   PLT_StateVariable::OnSendCompleted
  189
++---------------------------------------------------------------------*/
  190
+void
  191
+PLT_StateVariable::OnSendCompleted()
  192
+{
  193
+  if(m_ShouldClearOnSend)
  194
+      m_Value = m_DefaultValue;
  195
+}
  196
+
  197
+/*----------------------------------------------------------------------
186 198
 |   PLT_StateVariable::ValidateValue
187 199
 +---------------------------------------------------------------------*/
188 200
 NPT_Result
10  lib/libUPnP/Platinum/Source/Core/PltStateVariable.h
@@ -115,8 +115,9 @@ class PLT_StateVariable
115 115
      it is an allowed value. Once the value is validated, it is marked for eventing by
116 116
      calling the PLT_Service AddChanged function.
117 117
      @param value new state variable value. Can be a comma separated list of values.
  118
+     @param clearonsend whether the statevariable should be cleared immediatly after sending
118 119
      */
119  
-    NPT_Result SetValue(const char* value);
  120
+    NPT_Result SetValue(const char* value, const bool clearonsend = false);
120 121
     
121 122
     /**
122 123
      Validate the new value of the state variable.
@@ -173,6 +174,12 @@ class PLT_StateVariable
173 174
     bool IsReadyToPublish();
174 175
     
175 176
     /**
  177
+     * If this statevariable should clear after sending to all subscribers, clears the value without
  178
+     * eventing the change
  179
+     */
  180
+    void OnSendCompleted();
  181
+
  182
+    /**
176 183
      Serialize the state variable into xml.
177 184
      */
178 185
 	NPT_Result Serialize(NPT_XmlElementNode& node);
@@ -189,6 +196,7 @@ class PLT_StateVariable
189 196
     NPT_String              m_DefaultValue;
190 197
     bool                    m_IsSendingEvents;
191 198
     bool                    m_IsSendingEventsIndirectly;
  199
+    bool                    m_ShouldClearOnSend;
192 200
     NPT_TimeInterval        m_Rate;
193 201
     NPT_TimeStamp           m_LastEvent;
194 202
     NPT_Array<NPT_String*>  m_AllowedValues;
6  xbmc/music/MusicDatabase.cpp
@@ -4183,6 +4183,10 @@ bool CMusicDatabase::RemoveSongsFromPath(const CStdString &path1, CSongMap &song
4183 4183
 
4184 4184
       m_pDS->close();
4185 4185
 
  4186
+      //TODO: move this below the m_pDS->exec block, once UPnP doesn't rely on this anymore
  4187
+      for (unsigned int i = 0; i < ids.size(); i++)
  4188
+        AnnounceRemove("song", ids[i]);
  4189
+
4186 4190
       // and delete all songs, and anything linked to them
4187 4191
       sql = "delete from song where idSong in " + songIds;
4188 4192
       m_pDS->exec(sql.c_str());
@@ -4193,8 +4197,6 @@ bool CMusicDatabase::RemoveSongsFromPath(const CStdString &path1, CSongMap &song
4193 4197
       sql = "delete from karaokedata where idSong in " + songIds;
4194 4198
       m_pDS->exec(sql.c_str());
4195 4199
 
4196  
-      for (unsigned int i = 0; i < ids.size(); i++)
4197  
-        AnnounceRemove("song", ids[i]);
4198 4200
     }
4199 4201
     // and remove the path as well (it'll be re-added later on with the new hash if it's non-empty)
4200 4202
     sql = "delete from path" + where;
1  xbmc/network/upnp/UPnP.cpp
@@ -183,6 +183,7 @@ class CMediaBrowser : public PLT_SyncMediaBrowser,
183 183
             path += "/";
184 184
         }
185 185
 
  186
+        CLog::Log(LOGDEBUG, "UPNP: notfified container update %s", (const char*)path);
186 187
         CGUIMessage message(GUI_MSG_NOTIFY_ALL, 0, 0, GUI_MSG_UPDATE_PATH);
187 188
         message.SetStringParam(path.GetChars());
188 189
         g_windowManager.SendThreadMessage(message);
199  xbmc/network/upnp/UPnPServer.cpp
... ...
@@ -1,13 +1,16 @@
1 1
 #include "UPnPServer.h"
2 2
 #include "UPnPInternal.h"
  3
+#include "Application.h"
3 4
 #include "GUIViewState.h"
4 5
 #include "Platinum.h"
5 6
 #include "ThumbLoader.h"
  7
+#include "interfaces/AnnouncementManager.h"
6 8
 #include "filesystem/Directory.h"
7 9
 #include "filesystem/MusicDatabaseDirectory.h"
8 10
 #include "filesystem/VideoDatabaseDirectory.h"
9 11
 #include "guilib/Key.h"
10 12
 #include "music/tags/MusicInfoTag.h"
  13
+#include "settings/GUISettings.h"
11 14
 #include "utils/log.h"
12 15
 #include "utils/md5.h"
13 16
 #include "utils/StringUtils.h"
@@ -16,6 +19,7 @@
16 19
 #include "video/VideoDatabase.h"
17 20
 
18 21
 using namespace std;
  22
+using namespace ANNOUNCEMENT;
19 23
 using namespace XFILE;
20 24
 
21 25
 namespace UPNP
@@ -23,6 +27,28 @@ namespace UPNP
23 27
 
24 28
 NPT_UInt32 CUPnPServer::m_MaxReturnedItems = 0;
25 29
 
  30
+const char* audio_containers[] = { "musicdb://1/", "musicdb://2/", "musicdb://3/",
  31
+                                   "musicdb://4/", "musicdb://6/", "musicdb://9/",
  32
+                                   "musicdb://10/" };
  33
+
  34
+const char* video_containers[] = { "videodb://1/2/", "videodb://2/2/", "videodb://4/",
  35
+                                   "videodb://5/"  };
  36
+
  37
+/*----------------------------------------------------------------------
  38
+|   CUPnPServer::CUPnPServer
  39
++---------------------------------------------------------------------*/
  40
+CUPnPServer::CUPnPServer(const char* friendly_name, const char* uuid /*= NULL*/, int port /*= 0*/) :
  41
+    PLT_MediaConnect(friendly_name, false, uuid, port),
  42
+    PLT_FileMediaConnectDelegate("/", "/"),
  43
+    m_scanning(g_application.IsMusicScanning() || g_application.IsVideoScanning())
  44
+{
  45
+}
  46
+
  47
+CUPnPServer::~CUPnPServer()
  48
+{
  49
+    ANNOUNCEMENT::CAnnouncementManager::RemoveAnnouncer(this);
  50
+}
  51
+
26 52
 /*----------------------------------------------------------------------
27 53
 |   CUPnPServer::ProcessGetSCPD
28 54
 +---------------------------------------------------------------------*/
@@ -42,12 +68,100 @@ CUPnPServer::ProcessGetSCPD(PLT_Service*                  service,
42 68
 NPT_Result
43 69
 CUPnPServer::SetupServices()
44 70
 {
45  
-  PLT_MediaConnect::SetupServices();
46  
-  PLT_Service* service = NULL;
47  
-  NPT_Result result = FindServiceById("urn:upnp-org:serviceId:ContentDirectory", service);
48  
-  if (service)
49  
-    service->SetStateVariable("SortCapabilities", "res@duration,res@size,res@bitrate,dc:date,dc:title,dc:size,upnp:album,upnp:artist,upnp:albumArtist,upnp:episodeNumber,upnp:genre,upnp:originalTrackNumber,upnp:rating");
50  
-  return result;
  71
+    PLT_MediaConnect::SetupServices();
  72
+    PLT_Service* service = NULL;
  73
+    NPT_Result result = FindServiceById("urn:upnp-org:serviceId:ContentDirectory", service);
  74
+    if (service)
  75
+      service->SetStateVariable("SortCapabilities", "res@duration,res@size,res@bitrate,dc:date,dc:title,dc:size,upnp:album,upnp:artist,upnp:albumArtist,upnp:episodeNumber,upnp:genre,upnp:originalTrackNumber,upnp:rating");
  76
+
  77
+    m_scanning = true;
  78
+    OnScanCompleted(AudioLibrary);
  79
+    m_scanning = true;
  80
+    OnScanCompleted(VideoLibrary);
  81
+
  82
+    // now safe to start passing on new notifications
  83
+    ANNOUNCEMENT::CAnnouncementManager::AddAnnouncer(this);
  84
+
  85
+    return result;
  86
+}
  87
+
  88
+/*----------------------------------------------------------------------
  89
+|   CUPnPServer::OnScanCompleted
  90
++---------------------------------------------------------------------*/
  91
+void
  92
+CUPnPServer::OnScanCompleted(int type)
  93
+{
  94
+    if (type == AudioLibrary) {
  95
+        for (size_t i = 0; i < sizeof(audio_containers)/sizeof(audio_containers[0]); i++)
  96
+            UpdateContainer(audio_containers[i]);
  97
+    }
  98
+    else if (type == VideoLibrary) {
  99
+        for (size_t i = 0; i < sizeof(video_containers)/sizeof(video_containers[0]); i++)
  100
+            UpdateContainer(video_containers[i]);
  101
+    }
  102
+    else
  103
+        return;
  104
+    m_scanning = false;
  105
+    PropagateUpdates();
  106
+}
  107
+
  108
+/*----------------------------------------------------------------------
  109
+|   CUPnPServer::UpdateContainer
  110
++---------------------------------------------------------------------*/
  111
+void
  112
+CUPnPServer::UpdateContainer(const string& id)
  113
+{
  114
+    map<string,pair<bool, unsigned long> >::iterator itr = m_UpdateIDs.find(id);
  115
+    unsigned long count = 0;
  116
+    if (itr != m_UpdateIDs.end())
  117
+        count = ++itr->second.second;
  118
+    m_UpdateIDs[id] = make_pair(true, count);
  119
+    PropagateUpdates();
  120
+}
  121
+
  122
+/*----------------------------------------------------------------------
  123
+|   CUPnPServer::PropagateUpdates
  124
++---------------------------------------------------------------------*/
  125
+void
  126
+CUPnPServer::PropagateUpdates()
  127
+{
  128
+    PLT_Service* service = NULL;
  129
+    NPT_String current_ids;
  130
+    string buffer;
  131
+    map<string,pair<bool, unsigned long> >::iterator itr;
  132
+
  133
+    if (m_scanning || !g_guiSettings.GetBool("services.upnpannounce"))
  134
+        return;
  135
+
  136
+    NPT_CHECK_LABEL(FindServiceById("urn:upnp-org:serviceId:ContentDirectory", service), failed);
  137
+
  138
+    // we pause, and we must retain any changes which have not been
  139
+    // broadcast yet
  140
+    NPT_CHECK_LABEL(service->PauseEventing(), failed);
  141
+    NPT_CHECK_LABEL(service->GetStateVariableValue("ContainerUpdateIDs", current_ids), failed);
  142
+    buffer = (const char*)current_ids;
  143
+    if (!buffer.empty())
  144
+        buffer.append(",");
  145
+
  146
+    // only broadcast ids with modified bit set
  147
+    for (itr = m_UpdateIDs.begin(); itr != m_UpdateIDs.end(); ++itr) {
  148
+        if (itr->second.first) {
  149
+            buffer.append(StringUtils::Format("%s,%ld,", itr->first.c_str(), itr->second.second).c_str());
  150
+            itr->second.first = false;
  151
+        }
  152
+    }
  153
+
  154
+    // set the value, Platinum will clear ContainerUpdateIDs after sending
  155
+    NPT_CHECK_LABEL(service->SetStateVariable("ContainerUpdateIDs", buffer.substr(0,buffer.size()-1).c_str(), true), failed);
  156
+    NPT_CHECK_LABEL(service->IncStateVariable("SystemUpdateID"), failed);
  157
+
  158
+    service->PauseEventing(false);
  159
+    return;
  160
+
  161
+failed:
  162
+    // should attempt to start eventing on a failure
  163
+    if (service) service->PauseEventing(false);
  164
+    CLog::Log(LOGERROR, "UPNP: Unable to propagate updates");
51 165
 }
52 166
 
53 167
 /*----------------------------------------------------------------------
@@ -202,6 +316,79 @@ CUPnPServer::Build(CFileItemPtr                  item,
202 316
 }
203 317
 
204 318
 /*----------------------------------------------------------------------
  319
+|   CUPnPServer::Announce
  320
++---------------------------------------------------------------------*/
  321
+void
  322
+CUPnPServer::Announce(AnnouncementFlag flag, const char *sender, const char *message, const CVariant &data)
  323
+{
  324
+    NPT_String path;
  325
+    int item_id;
  326
+    string item_type;
  327
+
  328
+    if (strcmp(sender, "xbmc"))
  329
+        return;
  330
+
  331
+    if (strcmp(message, "OnUpdate") && strcmp(message, "OnRemove")
  332
+        && strcmp(message, "OnScanStarted") && strcmp(message, "OnScanFinished"))
  333
+        return;
  334
+
  335
+    if (data.isNull()) {
  336
+        if (!strcmp(message, "OnScanStarted")) {
  337
+            m_scanning = true;
  338
+        }
  339
+        else if (!strcmp(message, "OnScanFinished")) {
  340
+            OnScanCompleted(flag);
  341
+        }
  342
+    }
  343
+    else {
  344
+        // handle both updates & removals
  345
+        if (!data["item"].isNull()) {
  346
+            item_id = data["item"]["id"].asInteger();
  347
+            item_type = data["item"]["type"].asString();
  348
+        }
  349
+        else {
  350
+            item_id = data["id"].asInteger();
  351
+            item_type = data["type"].asString();
  352
+        }
  353
+
  354
+        // we always update 'recently added' nodes along with the specific container,
  355
+        // as we don't differentiate 'updates' from 'adds' in RPC interface
  356
+        if (flag == VideoLibrary) {
  357
+            if(item_type == "episode") {
  358
+                CVideoDatabase db;
  359
+                if (!db.Open()) return;
  360
+                int show_id = db.GetTvShowForEpisode(item_id);
  361
+                UpdateContainer(StringUtils::Format("videodb://2/2/%d/", show_id));
  362
+                UpdateContainer("videodb://5/");
  363
+            }
  364
+            else if(item_type == "tvshow") {
  365
+                UpdateContainer("videodb://2/2/");
  366
+                UpdateContainer("videodb://5/");
  367
+            }
  368
+            else if(item_type == "movie") {
  369
+                UpdateContainer("videodb://1/2/");
  370
+                UpdateContainer("videodb://4/");
  371
+            }
  372
+            else if(item_type == "musicvideo") {
  373
+                UpdateContainer("videodb://4/");
  374
+            }
  375
+        }
  376
+        else if (flag == AudioLibrary && item_type == "song") {
  377
+            // we also update the 'songs' container is maybe a performance drop too
  378
+            // high? would need to check if slow clients even cache at all anyway
  379
+            CMusicDatabase db;
  380
+            CAlbum album;
  381
+            if (!db.Open()) return;
  382
+            if (db.GetAlbumFromSong(item_id, album)) {
  383
+                UpdateContainer(StringUtils::Format("musicdb://3/%ld", album.idAlbum));
  384
+                UpdateContainer("musicdb://4/");
  385
+                UpdateContainer("musicdb://6/");
  386
+            }
  387
+        }
  388
+    }
  389
+}
  390
+
  391
+/*----------------------------------------------------------------------
205 392
 |   TranslateWMPObjectId
206 393
 +---------------------------------------------------------------------*/
207 394
 static NPT_String TranslateWMPObjectId(NPT_String id)
17  xbmc/network/upnp/UPnPServer.h
@@ -19,6 +19,7 @@
19 19
  *
20 20
  */
21 21
 #include "PltMediaConnect.h"
  22
+#include "interfaces/IAnnouncer.h"
22 23
 #include "FileItem.h"
23 24
 
24 25
 class CThumbLoader;
@@ -29,13 +30,13 @@ namespace UPNP
29 30
 {
30 31
 
31 32
 class CUPnPServer : public PLT_MediaConnect,
32  
-                    public PLT_FileMediaConnectDelegate
  33
+                    public PLT_FileMediaConnectDelegate,
  34
+                    public ANNOUNCEMENT::IAnnouncer
33 35
 {
34 36
 public:
35  
-    CUPnPServer(const char* friendly_name, const char* uuid = NULL, int port = 0) :
36  
-        PLT_MediaConnect(friendly_name, false, uuid, port),
37  
-        PLT_FileMediaConnectDelegate("/", "/") {
38  
-    }
  37
+    CUPnPServer(const char* friendly_name, const char* uuid = NULL, int port = 0);
  38
+    ~CUPnPServer();
  39
+    virtual void Announce(ANNOUNCEMENT::AnnouncementFlag flag, const char *sender, const char *message, const CVariant &data);
39 40
 
40 41
     // PLT_MediaServer methods
41 42
     virtual NPT_Result OnBrowseMetadata(PLT_ActionReference&          action,
@@ -90,6 +91,10 @@ class CUPnPServer : public PLT_MediaConnect,
90 91
 
91 92
 
92 93
 private:
  94
+    void OnScanCompleted(int type);
  95
+    void UpdateContainer(const std::string& id);
  96
+    void PropagateUpdates();
  97
+
93 98
     PLT_MediaObject* Build(CFileItemPtr                  item,
94 99
                            bool                          with_count,
95 100
                            const PLT_HttpRequestContext& context,
@@ -117,6 +122,8 @@ class CUPnPServer : public PLT_MediaConnect,
117 122
     NPT_Mutex                       m_FileMutex;
118 123
     NPT_Map<NPT_String, NPT_String> m_FileMap;
119 124
 
  125
+    std::map<std::string, std::pair<bool, unsigned long> > m_UpdateIDs;
  126
+    bool m_scanning;
120 127
 public:
121 128
     // class members
122 129
     static NPT_UInt32 m_MaxReturnedItems;
1  xbmc/settings/GUISettings.cpp
@@ -829,6 +829,7 @@ void CGUISettings::Initialize()
829 829
 
830 830
   CSettingsCategory* srvUpnp = AddCategory(SETTINGS_SERVICE, "upnp", 20187);
831 831
   AddBool(srvUpnp, "services.upnpserver", 21360, false);
  832
+  AddBool(srvUpnp, "services.upnpannounce", 20188, true);
832 833
   AddBool(srvUpnp, "services.upnprenderer", 21881, false);
833 834
 
834 835
 #ifdef HAS_WEB_SERVER
5  xbmc/settings/GUIWindowSettingsCategory.cpp
@@ -737,6 +737,11 @@ void CGUIWindowSettingsCategory::UpdateSettings()
737 737
       CGUIControl *pControl = (CGUIControl *)GetControl(pSettingControl->GetID());
738 738
       if (pControl) pControl->SetEnabled(g_guiSettings.GetBool("services.esenabled"));
739 739
     }
  740
+    else if (strSetting.Equals("services.upnpannounce"))
  741
+    {
  742
+      CGUIControl *pControl = (CGUIControl *)GetControl(pSettingControl->GetID());
  743
+      pControl->SetEnabled(g_guiSettings.GetBool("services.upnpserver"));
  744
+    }
740 745
     else if (strSetting.Equals("audiocds.quality"))
741 746
     { // only visible if we are doing non-WAV ripping
742 747
       CGUIControl *pControl = (CGUIControl *)GetControl(pSettingControl->GetID());
24  xbmc/video/VideoDatabase.cpp
@@ -2731,13 +2731,15 @@ void CVideoDatabase::DeleteMovie(const CStdString& strFilenameAndPath, bool bKee
2731 2731
       m_pDS->exec(strSQL.c_str());
2732 2732
     }
2733 2733
 
  2734
+    //TODO: move this below CommitTransaction() once UPnP doesn't rely on this anymore
  2735
+    if (!bKeepId)
  2736
+      AnnounceRemove("movie", idMovie);
  2737
+
2734 2738
     CStdString strPath, strFileName;
2735 2739
     SplitPath(strFilenameAndPath,strPath,strFileName);
2736 2740
     InvalidatePathHash(strPath);
2737 2741
     CommitTransaction();
2738 2742
 
2739  
-    if (!bKeepId)
2740  
-      AnnounceRemove("movie", idMovie);
2741 2743
   }
2742 2744
   catch (...)
2743 2745
   {
@@ -2801,12 +2803,14 @@ void CVideoDatabase::DeleteTvShow(const CStdString& strPath, bool bKeepId /* = f
2801 2803
       m_pDS->exec(strSQL.c_str());
2802 2804
     }
2803 2805
 
  2806
+    //TODO: move this below CommitTransaction() once UPnP doesn't rely on this anymore
  2807
+    if (!bKeepId)
  2808
+      AnnounceRemove("tvshow", idTvShow);
  2809
+
2804 2810
     InvalidatePathHash(strPath);
2805 2811
 
2806 2812
     CommitTransaction();
2807 2813
 
2808  
-    if (!bKeepId)
2809  
-      AnnounceRemove("tvshow", idTvShow);
2810 2814
   }
2811 2815
   catch (...)
2812 2816
   {
@@ -2840,6 +2844,10 @@ void CVideoDatabase::DeleteEpisode(const CStdString& strFilenameAndPath, int idE
2840 2844
       }
2841 2845
     }
2842 2846
 
  2847
+    //TODO: move this below CommitTransaction() once UPnP doesn't rely on this anymore
  2848
+    if (!bKeepId)
  2849
+      AnnounceRemove("episode", idEpisode);
  2850
+
2843 2851
     CStdString strSQL;
2844 2852
     strSQL=PrepareSQL("delete from actorlinkepisode where idEpisode=%i", idEpisode);
2845 2853
     m_pDS->exec(strSQL.c_str());
@@ -2862,8 +2870,6 @@ void CVideoDatabase::DeleteEpisode(const CStdString& strFilenameAndPath, int idE
2862 2870
       m_pDS->exec(strSQL.c_str());
2863 2871
     }
2864 2872
 
2865  
-    if (!bKeepId)
2866  
-      AnnounceRemove("episode", idEpisode);
2867 2873
   }
2868 2874
   catch (...)
2869 2875
   {
@@ -2922,13 +2928,15 @@ void CVideoDatabase::DeleteMusicVideo(const CStdString& strFilenameAndPath, bool
2922 2928
       m_pDS->exec(strSQL.c_str());
2923 2929
     }
2924 2930
 
  2931
+    //TODO: move this below CommitTransaction() once UPnP doesn't rely on this anymore
  2932
+    if (!bKeepId)
  2933
+      AnnounceRemove("musicvideo", idMVideo);
  2934
+
2925 2935
     CStdString strPath, strFileName;
2926 2936
     SplitPath(strFilenameAndPath,strPath,strFileName);
2927 2937
     InvalidatePathHash(strPath);
2928 2938
     CommitTransaction();
2929 2939
 
2930  
-    if (!bKeepId)
2931  
-      AnnounceRemove("musicvideo", idMVideo);
2932 2940
   }
2933 2941
   catch (...)
2934 2942
   {

0 notes on commit 59ca873

Please sign in to comment.
Something went wrong with that request. Please try again.