• 1
  • 3
  • 4
  • 5(current)
  • 6
  • 7
  • 9
XBMC AJAX Interface (BETA)
#61
A user of hhtpapi can use other commands to screw up xbmc such as the Config ones or even just haphazard deletion of files. There has to be a level of trust. I will place a warning in the online manual.

Reply
#62
nad, its not about causing problems. you can always break xbmc. in fact, its rather easy to do. its about consistency.

the api should only allow access to the same exact queries that the gui uses and not allow arbitrary queries. knowledge of table relations is required to get information correctly. instead of arbitrary queries, some form of translation of the parameter into a smartplaylist could work. it allows searching for songs in almost any way possible.

but ive voiced my opinion and will leave it at that.
Always read the XBMC online-manual, FAQ and search the forum before posting.
Do not e-mail XBMC-Team members directly asking for support. Read/follow the forum rules.
For troubleshooting and bug reporting please make sure you read this first.
Reply
#63
kraqh3d: I take your point but I see httpapi providing more flexible functionality than just a representation of the gui - client developers may want to do things differently to xbmc gui developers. Also providing a complete exposure of all the gui interfaces to the music database would have meant an awful lot of httpapi code which I didn't fancy.

Reply
#64
Thanks nad, this is great!

I've got some ajax that gives a simple textbox and search button. The results come back in and it puts a play button next to each result.

Very simple for now, but it gets me started. It seems pretty quick on my music library. Some queries are returning songs that they shouldn't, and i can't figure out why. Also, To do wildcards in the SQL I have to use 2 % symbols. Is this correct? WHERE strTitle = '%%love%%'

Here is the initial version of the code if anyone else wants to play:

You will need the latest t3ch release or cvs build, you must enable the webserver, and you have to save this code into an html file and upload it into the /web/ directory.

Code:
<script type="text/javascript">

function createRequestObject() {
    var ro;
    var browser = navigator.appName;
    if(browser == "Microsoft Internet Explorer"){
        ro = new ActiveXObject("Microsoft.XMLHTTP");
    }else{
        ro = new XMLHttpRequest();
    }
    return ro;
}

var http = createRequestObject();



function PlayMedia(mediapath){

     var url = '/xbmcCmds/xbmcHttp?command=playfile&parameter='+mediapath;
     http.open("get",url);
       http.send(null);

}

function QueryMusicDatabase(query){
alert("searching for: "+query);

document.getElementById("results").innerHTML = "";

var sqlquery = "SELECT strPath, strFileName, strTitle, strAlbum, strArtist  from songview WHERE strTitle LIKE '%%"+query+"%%';";
     var url = "/xbmcCmds/xbmcHttp?command=QueryMusicDatabase&parameter="+sqlquery;
resultsHTML = "<b>"+unescape(sqlquery)+"</b><br><br>";

    http.open("get",url);
    http.onreadystatechange = function(){
        if(http.readyState == 4){
        responseArr = http.responseText.split("<li>");

            while(responseArr.length>1){

            //We know that we pulled 5 columns,
            //so we can pop off 5 at a time for each song
            strArtist = responseArr.pop();
            strAlbum = responseArr.pop();
            strTitle = responseArr.pop();
            strFileName = responseArr.pop();
            strPath = responseArr.pop();
            
            //document.write("strPath:"+strPath+"<br>");
            //document.write("strAlbum:"+strAlbum+"<br>");
            //document.write("strTitle:"+strTitle+"<br>");
            //document.write("strFileName:"+strFileName+"<br>");
            //document.write("strArtist:"+strArtist+"<br>");
            //document.write("fullpath:"+strPath+"/"+strFileName+"<br>");
            //document.write("<br><br>"+"<br>");


            resultsHTML += "<a href='javascript:PlayMedia(\""+escape(strPath)+"/"+escape(strFileName)+"\");'><img src='http://liquidice629.googlepages.com/play.gif' border=0>&nbsp;"+strTitle+"</a><br><b>Album:</b> "+strAlbum+"<br><b>Artist:</b> "+strArtist+"<br><br>";


            }


document.getElementById("results").innerHTML = resultsHTML;

        }
    }
    http.send(null);

}

</script>



<input type="text" name="query" id="query">
&nbsp;&nbsp;&nbsp;
<a href="javascript:QueryMusicDatabase(document.getElementById('query').value);">Search</a><br><br>
<div id="results">

</div>

I see lots of great uses for this new api call. Now we can search and launch songs and playlists from all kinds of desktop widgets. I can finally implement the on screen keyboard search box into my touchpanel layout, and we can even create browser addons that use the search api

(i could see an xbmc music library search in the corner of my firefox bar being useful when i have a song stuck in my head and want to quickly find it and play it on my xbmc)

More to come soon...
Reply
#65
Hi LiquidIce: I suggest you look in the xbmc source file MusicDatabase.cpp for useful SQL queries. %% does seem to be how to specify a wildcard.

Reply
#66
I think I got the ajax beta 3 versin of this but the album art doesnt show , is there a simple fix, is there people still using this program?
Reply
#67
KingJames Wrote:I think I got the ajax beta 3 versin of this but the album art doesnt show , is there a simple fix, is there people still using this program?

The correct question is: is there still someone working on it? It was a wonderful project, but it seems nobody has finished it Sad
Reply
#68
I'm taking another shot at making this useful..

There are 2 things that I could really use some help with

1. Album Art.
It's almost a year later, and still no way to get album art in IE. The base64 way of it working in firefox was nice, but if I release a new version of this ajax browser I want it to be compatible with ie7 and FF.
I have tried everything I can possibly think of to get this working... Here is the latest SPYCE code I made to attempt to send the thumbnail jpeg data with the correct http headers. It still does not work. I get some data back, but it's not a jpeg.
Code:
<%
import xbmc, base64
response.setContentType('image/jpeg')

thumbfile = 'q:\\userdata\\Thumbnails\\Music\\d1fa1e1b.tbn'
file = open(thumbfile, 'r+b').read()
print base64.decodestring(file)
%>

Can we just link /web/thumbs/ to the thumbnails directory in the userdata folder? Or is there a way to make this SPYCE thing work? Also if I was able to get this to work, how can I make my SPYCE file dynamic?

for example if I call:
getimage.spy?thumbnail=d1fa1e1b.tbn

how can i get the 'd1fa1e1b.tbn' into my python script? Does it parse http get variables when it runs?



2. Bouncing between music browser and music playlist

In my experience, the fastest way to show a large amount of data in a webpage served up by xbmc is to use the xbmcCommand("navigate", "music")
I've tried it with GetMediaLocation and many other ways but due to encoding issues, the way that is used in default.asp of the original webapi is still the best way. The problem is, if I want to view my music playlist ( xbmcCommand("navigate", "musicplaylist") ) then i lose my location in the music browser (have to start back at the root of the shares)

This makes it extremely difficult to quickly switch between playlists and the browser. A possible workaround is to instead use the GetPlayListContents command, but this only returns a list of filenames, which has to be (slowly) parsed in javascript and suffers from various encoding issues on files with wierd characters.

--

Lots of cool things are still to come if I can get through these problems... I've been doing some neat stuff with the SQL queries that you guys added a few months back, so thanks for that! Any help on these two issues would be greatly appreciated.

-LiquidIce
Reply
#69
1) if you're setting the content-type to image/jpeg, you dont have to encode as base64. you just send it as straight binary. this is what would happen if the thumb folder was linked to the webserver.

2) the navigate command isnt an httpapi command. its one of the local webserver remote control. but i thought it behaved more like the gui and retained the last location. anyway, im not really sure how that works. it gets the items into a CFileItemList (same as GetMediaLocation). the difference is that GetMediaLocation translates the items into html. how do you retrieve the items from the navigate command?
Always read the XBMC online-manual, FAQ and search the forum before posting.
Do not e-mail XBMC-Team members directly asking for support. Read/follow the forum rules.
For troubleshooting and bug reporting please make sure you read this first.
Reply
#70
I tried that. If i just output what was read I do not get a valid jpeg:
Code:
<%
import xbmc
response.setContentType('image/jpeg')

thumbfile = 'q:\\userdata\\Thumbnails\\Music\\d1fa1e1b.tbn'
file = open(thumbfile, 'r+').read()
print file
%>

--

I was able to get HTTP GET variables in SPYCE by using:

mypage.spy?myvariable1=123
Code:
print request.get("myvariable1")   //outputs 123

I made the images work in Firefox by hacking together this script that jams everything into an iframe:

<iframe border="0" src="albumiframe.spy?thumb=35508e50.tbn&amp;strPath=smb%3A//192.168.1.2/MP3s/MyAlbum/" frameborder="0" height="100" width="100"></iframe>

albumiframe.spy:
Code:
<body topmargin=0 leftmargin=0 style="overflow:hidden">
<a href="javascript:PlayMedia('<%print request.get("strPath")[0]%>')"><img border=0 width="100" height="100" src="data:image/jpg;base64,
<%
import xbmc, base64

thumbfile = 'q:\\userdata\\Thumbnails\\Music\\'+request.get("thumb")[0]
file = open(thumbfile, 'r+b').read()
print base64.encodestring(file)
%>
">
</body>


As for the Navigate command. The way i am currently doing it is using ASP to generate my entire songlist and just using javascript to insert that html block into my DIV. When I tried using the HTTPAPI commands to do the same thing, the javascript would get bogged down from having to parse apart the strings then build my playlists/directory list from the data.

Code:
<ul id="musiclibrary" align="left" class="musiclibrary">
<%
  var itemCount; // number of items in list
  var data;      // tmp var used in for loop
  var tmpType;   // holds isDir value
  var i;         // iterator

  navigatorstate = xbmcCommand("navigatorstate");

  if (navigatorstate == "pictures") {
    ItemIconPath = "images/image.png";
    ItemPlayIcon = "images/view.png";
    ItemAddIcon = "images/addtoplaylist.gif";
        CurrentPlayList = 0;
  }
  else if (navigatorstate == "music") {
    ItemIconPath = "images/music.png";
    ItemPlayIcon = "images/play.png";
    ItemAddIcon = "images/addtoplaylist.gif";
    CurrentPlayList = 0;
  }
  else if (navigatorstate == "videos") {
    ItemIconPath = "images/movie.png";
    ItemPlayIcon = "images/video.png";
    ItemAddIcon = "images/addtoplaylist.gif";
        CurrentPlayList = 2;
  }
  else {
        xbmcCommand("navigate", "music");
    ItemIconPath = "images/music.png";
    ItemPlayIcon = "images/play.png";
    ItemAddIcon = "images/addtoplaylist.gif";
        CurrentPlayList = 0;
    }
  
  if (isset("Action")) { xbmcCommand("navigate", Action); }
  if (isset("command")) {  
    if (command == "select") { xbmcCommand("catalog", "select," + item); }
  }

  itemCount = xbmcCommand("catalog","items");
  file = xbmcCommand("catalog","first");
  
  for (i = 0; i < itemCount; i = i + 1) {
    tmpType = xbmcCommand("catalog","type,"+i);


   if (tmpType == "directory") {  data = '  <li class="row' + (i % 2) + '" mediapath="'+ i + '" id="musiclibrary'+ i + '">  <span  style="height:40px">'; }
    else {  data = '  <li class="row' + (i % 2) + '" mediapath="'+ i + '" id="musiclibrary'+ i + '" >  <span style="height:40px">'; }
  
    
    if (tmpType == "directory") { data = data + '<span valign="center" align="left" id="musiclibArt'+ i +'"><img hspace="20" align="left" onclick="javascript:navigateToLocation(\''+ i +'\');" src="images/folder_small.png"/></span><div style="overflow: hidden; width: 60%;" id="musiclibSongInfo'+ i +'">'+ file +'</div>'; }
    else { data = data + '<span valign="center" align="left" id="musiclibArt'+ i +'"><img hspace="20" align="left" onclick="javascript:PlayMedia('+ i + ');" src="'+ ItemIconPath +'"/></span><div style="overflow: hidden; width: 60%;" id="musiclibSongInfo'+ i +'">'+ file +'</div>';  }
    
    data = data + "</span>";

    data = data + '<div style="position: absolute; right: 0pt; top: 0px; width: 100px; vertical-align: top;" id="itemControls'+ i +'">';
    
    if (tmpType == "directory") { data = data + '<a href="javascript:navigateToLocation('+ i + ')" ><img border="0" src="images/openfolder.png" /></a>';  }
    else { data = data + '<a href="javascript:PlayId('+ i + ');" ><img border="0" src="'+ ItemPlayIcon +'"  /></a>';  }
    


    if (file != "..") data = data + '<img border="0" onclick="javascript:SetCurrentPlaylist('+CurrentPlayList+');AddIdToPlayList('+ i + ')" src="'+ ItemAddIcon +'"/>';
    data = data + '</div></li>';
    write(data+"\n");
    file = xbmcCommand("catalog","next");
  }
%>
</ul>
So with this method, most of the work is being done by the xbox webserver and the client browser just inserts this data into the page and reacts when buttons are pressed. This method works great except when I run my script to generate the playlist (by first using the navigate command to navigate to 'musicplaylist' then running through a similar loop as the above) after that when i navigate back to 'music' i am back at the root of my shares.

I realize this may just be the way that it works, but i'm hoping to come up with an alternative solution to make this more usable. Maybe I am approaching this the wrong way? Any tips would be appreciated.
Reply
#71
Glad to see that this is still being developed.

I also like the xbmc distributed, even if the audio sync is off by .5 sec - 1 sec. It is a useful tool for monitoring your xboxes on the network.
TV Mosaic on Windows 10 as PVR Backend |  1 RaspberryPI 3 Client (LibreElec) | Amazon FireTV box | 5 Amazon FireTV sticks | FireTV Cube | 2 Nvidia Shield TV
Tuners: HD HomeRun 4 ATSC (OTA) | IPTV
Reply
#72
that works in firefox because firefox will accept a base64 encoded mime object as text embedded in the html. the better solution which should work in any browser would be to just set the content type correctly and send the raw binary data. my guess is that print is the problem.
Always read the XBMC online-manual, FAQ and search the forum before posting.
Do not e-mail XBMC-Team members directly asking for support. Read/follow the forum rules.
For troubleshooting and bug reporting please make sure you read this first.
Reply
#73
I think you are right kraqh3d, I opened the thumbnail up in a hex editor and the write command starts to write out the binary data but chokes on NULL %00 \x00 or whatever you want to call it.

So I tried some other ways of writing the binary data:

#sys.stdout.write(file)
#os.write(1,file)

no luck there either. I'm beginning to think this is not possible with spyce.. :-(

My latest code which returns data until it gets to a NULL:
Code:
<%
import sys
thumbfile = 'q:\\userdata\\Thumbnails\\Music\\d1fa1e1b.tbn'
file = open(thumbfile, 'rwb').read()
response.setContentType('image/jpeg')
sys.stdout.write(file)
%>
Reply
#74
I did some more tests, and the entire page stops processing after the NULL. Is it possible that the webserver is causing the problem?

Code:
<%
import string
thumbfile = 'q:\\userdata\\Thumbnails\\Music\\d1fa1e1b.tbn'
file = open(thumbfile, 'rwb').readlines()
response.setContentType('image/jpeg')
print string.join(file, '')
print "more" #this never runs, the entire script is halted after it hits a NULL
%>
This text outside the main code will not be displayed either

Is there any other way to send the JPEG data to the browser?
Reply
#75
Just for S&G I decided to try to run this code on SPYCE for windows, and it works perfectly. The problem with sending a NULL character does not exist in spyce webserver for windows.

Code:
[[.import name=include ]]
[[\
  response.setContentType('image/jpeg')
  path = "10888eaf.tbn"
  response.write(include.dump(path, 1))
]]

I'm somewhat confused. If spyce is a complete the web server, then what is GoAhead used for? Or is goahead the main server and just relaying the data to the spyce webserver when it sees a .spy file?
Reply
  • 1
  • 3
  • 4
  • 5(current)
  • 6
  • 7
  • 9

Logout Mark Read Team Forum Stats Members Help
XBMC AJAX Interface (BETA)0