Kodi Community Forum
Virtual Python Folders - Printable Version

+- Kodi Community Forum (https://forum.kodi.tv)
+-- Forum: Development (https://forum.kodi.tv/forumdisplay.php?fid=32)
+--- Forum: Add-ons (https://forum.kodi.tv/forumdisplay.php?fid=26)
+--- Thread: Virtual Python Folders (/showthread.php?tid=27760)

Pages: 1 2 3 4 5 6 7 8 9


- jmarshall - 2007-08-16

Cool.

One thing we need to watch out for is where (if anywhere) the ListItem's you are creating (python versions, and the CFileItem item member) are being deallocated.

You add a reference on creation, but are they ever dereferenced? A breakpoint in ListItem_Dealloc will do the trick.

Cheers,
Jonathan


- jmarshall - 2007-08-16

Yes, as I expected, ListItem_Dealloc is never being called, due to the Py_INCREF() you are doing.

I expect you probably don't want the Py_INCREF() in there, as really we're using the ListItem * as a temporary placeholder just so we can pass the item details on through. It'd be up to the scripter to keep it around if they wanted to.

Without the Py_INCREF() it should correctly call the deconstructer when it goes out of scope in python.

Seems to work nicely though, other than that memleak Smile

Cheers,
Jonathan


- Nuka1195 - 2007-08-16

ok, I'll change that.

Quote:Then expand the listitem creation with a method to set the tag info and we're done.

How would we pass the info to setDirectoryEntry(), individual items? or are you saying modify the listitem to accept more parameters?

or did I not understand that and the tag info you were refering to was just label, label2, icon and thumbnail?


- jmarshall - 2007-08-16

Exactly - mod the listitem so as to either take more params, or allow yourself a general "setinfo()" function that takes info,value pairs.


- Nuka1195 - 2007-08-16

The setInfo() might be better.

If the listitem was modded, would it just take new kwargs, so a scripter could add genre='Comedy'. You would again have a limited set of items. Should there be a limited set?

You could add an optional tuple of pairs: info=(['genre','Comedy'],['plot','This is the plot'],)

Either way, I'm still not sure what to do with them, I didn't find a e.g. setGenre() like there is a setLabel().


- spiff - 2007-08-16

fileitem.GetVideoInfoTag()->m_strPlot
fileitem->GetVideoInfoTag()->m_strGenre

and so on. have a blast


- Nuka1195 - 2007-08-16

Thanks, spiff Smile

Now to decide.

extend listitem with two options:
mode=0,1,2 or music,video,pictures
and
tags=(["tagname","value"],)

or add a setInfo() with the above

or maybe three new python methods:
setVideoTags()
setMusicTags()
setPicturesTags()


- Nuka1195 - 2007-08-16

Spiff, I remember you talking about the ability for scripts to set that information. What was your idea?


- spiff - 2007-08-16

that it should be possible, i had not really thought through it more than that

out of those alternatives i prefer the second. there's not much code to be shared here anyway and it's the most clear / hardest to make mistakes


- Unbehagen - 2007-08-16

Maybe we should move all of those methods to a new python module "xbmcplugin" to make it clear that they are only for that purpose?

Sorry for not being active. I currently have a lot of work to do. Thanks for improving those features further.

BTW: Is there any policy on when those changes in the branch will be merged and get into trunk? Would it be easy to merge the branch with the embedded browser with this branch?


- Nuka1195 - 2007-08-16

Ah, spiff. I should have checked here before.

What I did was enhanced the listitem, by adding two optional parameters type & tags. It seemed the easiest to me. If we do the 2nd method, then two calls need to be made to set the information. This is ok by me though, so I'll continue on to give a little test. It should be easy to move it to it's own method.

Unbehagen, the new listitem or if it get's changed to it's own method will be useful for regular scripts also.

As far as SVN is concerned, they'll say when it's ready. The embedded browser will never be merged as I understand it.

Edit: Spiff I'll make it it's own method, I think it will be cleaner code also. So you would call the method on the listitem. listitem.setInfo(), just like setLabel()


- Nuka1195 - 2007-08-16

Here is the setInfo() patch, see if this is the dircetion you want to go. For some reason ListItem.Rating did not show. i exchanged it with ListItem.Year and it worked, maybe a script error or maybe you can spot the mistake.

I'll check later, though someone can feel free to finish. Smile

Purist may want the tags argument to be a dictionary.

Code:
Index: xbmc/FileSystem/PluginDirectory.cpp
===================================================================
--- xbmc/FileSystem/PluginDirectory.cpp (revision 9959)
+++ xbmc/FileSystem/PluginDirectory.cpp (working copy)
@@ -70,6 +70,22 @@
   pItem->SetIconImage(item->GetIconImage());
   pItem->SetThumbnailImage(item->GetThumbnailImage());
   pItem->m_bIsFolder = bIsFolder;
+  if (item->HasVideoInfoTag())
+  {
+    pItem->GetVideoInfoTag()->m_strGenre = item->GetVideoInfoTag()->m_strGenre;
+    pItem->GetVideoInfoTag()->m_iYear = item->GetVideoInfoTag()->m_iYear;
+    pItem->GetVideoInfoTag()->m_strDirector = item->GetVideoInfoTag()->m_strDirector;
+    pItem->GetVideoInfoTag()->m_strMPAARating = item->GetVideoInfoTag()->m_strMPAARating;
+    pItem->GetVideoInfoTag()->m_strPlot = item->GetVideoInfoTag()->m_strPlot;
+    pItem->GetVideoInfoTag()->m_strRuntime = item->GetVideoInfoTag()->m_strRuntime;
+    pItem->GetVideoInfoTag()->m_strTitle = item->GetVideoInfoTag()->m_strTitle;
+  }
+  else if (item->HasMusicInfoTag())
+  {
+  }
+  else if (item->HasPictureInfoTag())
+  {
+  }
   pItem->SetLabelPreformated(true); // TODO: This is probably better not set once we have all the CFileItem stuff available.
   dir->m_listItems.Add(pItem);
}
Index: xbmc/lib/libPython/xbmcmodule/listitem.cpp
===================================================================
--- xbmc/lib/libPython/xbmcmodule/listitem.cpp (revision 9959)
+++ xbmc/lib/libPython/xbmcmodule/listitem.cpp (working copy)
@@ -269,6 +269,91 @@
     return Py_BuildValue("b", bOnOff);
   }

+  PyDoc_STRVAR(setInfo__doc__,
+    "setInfo(type, tags) -- Sets the listitem's media tags.\n"
+    "\n"
+    "type           : string - type of media(video/music/pictures).\n"
+    "tags           : list - tuple pairs of tag,value.\n"
+    "\n"
+    "*Note, You can use the above as keywords for arguments and skip certain optional arguments.\n"
+    "       Once you use a keyword, all following arguments require the keyword.\n"
+    "\n"
+    "example:\n"
+    "  - self.list.getSelectedItem().setInfo('video',[('Genre', 'Comedy',)])\n");
+
+  PyObject* ListItem_SetInfo(ListItem *self, PyObject *args, PyObject *kwds)
+  {
+    static char *keywords[] = { "type", "tags", NULL };
+    char *cType = NULL;
+    PyObject *pTagList = NULL;
+    if (!PyArg_ParseTupleAndKeywords(
+      args,
+      kwds,
+      "sO",
+      keywords,
+      &cType,
+      &pTagList))
+    {
+      return NULL;
+    }
+
+    if (pTagList == NULL || !PyObject_TypeCheck(pTagList, &PyList_Type))
+    {
+      PyErr_SetString(PyExc_TypeError, "tags object should be of type List");
+      return NULL;
+    }
+
+    PyGUILock();
+    for (int i = 0; i < PyList_Size(pTagList); i++)
+    {
+      PyObject *pTuple = NULL;
+      char *cTag = NULL;
+      char *cValue = NULL;
+      pTuple = PyList_GetItem(pTagList, i);
+      if (pTuple == NULL || !PyObject_TypeCheck(pTuple, &PyTuple_Type))
+      {
+        //PyErr_SetString(PyExc_TypeError, "List must only contain tuples");
+        continue;//return NULL;
+      }
+      if (!PyArg_ParseTuple(pTuple, "ss", &cTag, &cValue))
+      {
+        //PyErr_SetString(PyExc_TypeError, "Error unpacking tuple found in list");
+        continue;//return NULL;
+      }
+
+      if (strcmpi(cType, "video") == 0)
+      {
+        if (strcmpi(cTag, "genre") == 0)
+          self->item->GetVideoInfoTag()->m_strGenre = cValue;
+        else if (strcmpi(cTag, "year") == 0)
+          self->item->GetVideoInfoTag()->m_iYear = atoi(cValue);
+        else if (strcmpi(cTag, "director") == 0)
+          self->item->GetVideoInfoTag()->m_strDirector = cValue;
+        else if (strcmpi(cTag, "rating") == 0)
+          self->item->GetVideoInfoTag()->m_strMPAARating = cValue;
+        else if (strcmpi(cTag, "plot") == 0)
+          self->item->GetVideoInfoTag()->m_strPlot = cValue;
+        else if (strcmpi(cTag, "runtime") == 0)
+          self->item->GetVideoInfoTag()->m_strRuntime = cValue;
+        else if (strcmpi(cTag, "title") == 0)
+          self->item->GetVideoInfoTag()->m_strTitle = cValue;
+        CLog::Log(LOGDEBUG, __FUNCTION__" - Type: %s - Tag: %s - Value: %s ", cType, cTag, cValue);
+      }
+      else if (strcmpi(cType, "music") == 0)
+      {
+        CLog::Log(LOGDEBUG, __FUNCTION__" - Type: %s - Tag: %s - Value: %s ", cType, cTag, cValue);
+      }
+      else if (strcmpi(cType, "pictures") == 0)
+      {
+        CLog::Log(LOGDEBUG, __FUNCTION__" - Type: %s - Tag: %s - Value: %s ", cType, cTag, cValue);
+      }
+    }
+    PyGUIUnlock();
+  
+    Py_INCREF(Py_None);
+    return Py_None;
+  }
+
   PyMethodDef ListItem_methods[] = {
     {"getLabel" , (PyCFunction)ListItem_GetLabel, METH_VARARGS, getLabel__doc__},
     {"setLabel" , (PyCFunction)ListItem_SetLabel, METH_VARARGS, setLabel__doc__},
@@ -278,6 +363,7 @@
     {"setThumbnailImage", (PyCFunction)ListItem_SetThumbnailImage, METH_VARARGS, setThumbnailImage__doc__},
     {"select", (PyCFunction)ListItem_Select, METH_VARARGS, select__doc__},
     {"isSelected", (PyCFunction)ListItem_IsSelected, METH_VARARGS, isSelected__doc__},
+    {"setInfo", (PyCFunction)ListItem_SetInfo, METH_KEYWORDS, setInfo__doc__},
     {NULL, NULL, 0, NULL}
   };

Index: xbmc/lib/libPython/xbmcmodule/xbmcmodule.cpp
===================================================================
--- xbmc/lib/libPython/xbmcmodule/xbmcmodule.cpp (revision 9959)
+++ xbmc/lib/libPython/xbmcmodule/xbmcmodule.cpp (working copy)
@@ -37,7 +37,7 @@
  * start of xbmc methods
  *****************************************************************/
   PyDoc_STRVAR(setDirectoryEntry__doc__,
-    "setDirectoryEntry(handle, url, listitem, [,isFolder]) -- Callback function to pass directory contents back to XBMC.\n"
+    "setDirectoryEntry(handle, url, listitem [,isFolder]) -- Callback function to pass directory contents back to XBMC.\n"
     "\n"
     "handle      : Integer - handle the plugin was started with.\n"
     "url         : string - url of the entry. would be plugin:// for another virtual directory\n"
@@ -74,7 +74,6 @@

     ListItem *pListItem = NULL;
     pListItem = (ListItem *)pItem;
-    Py_INCREF(pListItem);

     // call the directory class to add our item
     DIRECTORY::CPluginDirectory::AddItem(handle, url, (CFileItem *)pListItem->item, bIsFolder);



- jmarshall - 2007-08-16

Looks good, but the CPluginDirectory::AddItem() should be much simpler:

CFileItem *pItem = new CFileItem(*item);
pItem->SetLabelPreformatted(); // shouldn't really be needed now?
m_listItems.Add(pItem);

CFileItem has a copy constructor that does all the copying for you Wink

Rating isn't set anywhere there - I presume you had it set before but it didn't work? It takes a float for videos.

Cheers,
Jonathan


- Nuka1195 - 2007-08-17

ok, will fix that,. thanks

I'm trying to change the python setInfo() method to take a dictionary. I'm getting some unresolved external links. I think I've fixed a couple, but could you figure the last one out?

http://pastebin.ca/660334

Edit: Without the preformatted=True. I can't override/set label2. Is that the desired behavior. I would like to be able to override label2

void CPluginDirectory::AddItem(int handle, CFileItem *item)

That's the new constructor



- jmarshall - 2007-08-17

Have fixed and committed to SVN with some slight modifications.

The XBMC_setDirectoryEntry() function possibly doesn't need URL and bIsFolder passed in to it unless you can't already set them on the listitem.

All you missed was the FUNCTION4(PyDict_Keys) prototype btw Smile