cancel
Showing results for 
Search instead for 
Did you mean: 
cancel

UCCX 8.x - how to play/write file prompts from/to Windows shares

9536
Views
10
Helpful
60
Comments

Problem:

It's a common requirement to play prompts that are saved as wave files on a Windows share. Starting UCCX 8.x the platform is Linux-based, thus there's no possibility to "mount" Windows shares easily.

A user might want to save prompts recorded by UCCX on to a Windows share.

Analysis:

UCCX must be enabled to communicate using the CIFS/SMB protocol. Also, the file should be cached in order to eliminate delays.

Solution:

**** DISCLAIMER: This is a proof of concept. I did not check whether the LGPL license of the JCIFS library is compatible with UCCX. USE THIS AT YOUR OWN RISK. I am not responsible for any damage this solution may cause. I cannot guarrantee this would work with your installation of UCCX. Tested with IP IVR System version: 8.0.2.11004-12. ****

I. reading a prompt from a Windows share

1. Download the JCIFS library, available at http://jcifs.samba.org/ (click the Download link, then download a recent file, for instance, jcifs-1.3.17.jar

2. Upload this JAR file to UCCX, using the System > Custom File Configuration. After uploading, make sure to select the file as a "Selected Classpath Entries":

uccx_classpath.PNG

3. Restart the CCX engine.

4. Make sure you've got set up the following: the file is saved using a correct codec and format (check System > System Parameters Configuration, look for the Media Parameters section); also, the file must be available in a Windows share (default shares - like c$ - might not work); and of course, you need to have a user and a password.

5. Create a UCCX script. Add all the variables steps you need (for instance, Accept, etc).

6. Add a new variable, of type java.io.ByteArrayInputStream. Name it byteArrayIS (for instance).

7. Add a new variable, of type String. Name it smbFileURL (for instance).

8. Add a new Set step. The result wariable would be smbFileURL. For the value, use the following format:

smb://domain;user:password@ipaddress/share/file.wav

For example:

smb://ipcc;filereader:SuperS3crEt!@10.232.128.68/Temp/friday.wav

This means: ipcc\filereader user with password SuperS3crEt! may read the contents of the file friday.wav on the server 10.232.128.68 within the Temp share.

For more possibilities of this URL, take a look at the JCIFS documentation at http://jcifs.samba.org/src/docs/api/jcifs/smb/SmbFile.html (scroll down to SMB URL Examples).

8. Add a new Set step. The result variable would be byteArrayIS. As for the value, paste in the following closure:

{

int bufSize = 4096; // buffer size, bytes

java.io.ByteArrayOutputStream baos = new java.io.ByteArrayOutputStream();

try {

    jcifs.smb.SmbFile smbFile = new jcifs.smb.SmbFile(smbFileURL);

    java.io.InputStream in = smbFile.getInputStream();

    byte[] bytesRead = new byte[bufSize];

    int bytesReadLength = 0;

    while(( bytesReadLength = in.read( bytesRead )) > 0 ) {

        baos.write(bytesRead,0,bytesReadLength);

    } //while

    in.close();

    baos.close();

} catch (Exception e) {

return null;

} //try..catch

return new java.io.ByteArrayInputStream(baos.toByteArray());

}

(for more information how this works, look at the end of this section).

9. Add a new Play Prompt step. Use the following value on the Prompt tab:

(Prompt) byteArrayIS

10. Test it. You should be able to hear the contents of the file prompt.

Screenshot:

uccx_smbfilemagic.PNG

(Click the image above to enlarge it).

What just happened?

The closure above dissected:

int bufSize = 4096; // buffer size, bytes

We define the read buffer size. 4096 bytes, in other words, 4 kilobytes seems to be alright, you can modify this to 8KB or 16KB if the file reads slowly.

java.io.ByteArrayOutputStream baos = new java.io.ByteArrayOutputStream();

Just a ByteArrayOutputStream to hold the prompt contents.

The following try..catch block contains:

jcifs.smb.SmbFile smbFile = new jcifs.smb.SmbFile(smbFileURL);

A new File (or more precisely, a SmbFile) object is constructed, with one parameter: smbFileURL.

Of course, you can do something more with it, for instance, check whether the file exists. Again, take a look at the JCIFS API docs.

java.io.InputStream in = smbFile.getInputStream();

This is where we access the InputStream of the above SmbFile.

byte[] bytesRead = new byte[bufSize];

A byte array, for buffering the file contents. The buffer size is defined in the bufSize local variable.

int bytesReadLength = 0;

Another local variable, for checking how many bytes have been read from the InputStream of the SmbFile object.

And then the only thing we need to do is just read the bytes from the InputStream (in chunks, to give it some speed), and copy these bytes to the ByteArrayOutputStream:

while (( bytesReadLength = in.read( bytesRead )) > 0 ) {

     baos.write(bytesRead,0,bytesReadLength);

} //while

Of course, it's always good to close the resources:

in.close();

baos.close();

The catch block will return null (in case something goes wrong), but you can also include something more useful.

return null;

But if everything goes perfect, we can return a ByteArrayInputStream (by flipping the ByteArrayOutputStream above):

return new java.io.ByteArrayInputStream(baos.toByteArray());

The Play Prompt step (and every prompt-related step) can work perfectly with InputStreams, including ByteArrayInputStreams, the only thing to remember is to cast them to type Prompt. It's easy:

(Prompt) byteArrayIS

So again, we create an InputStream out of the file (which is accessible thanks to the JCIFS library), read the contents of the file in chunks, write these chunks to an OutputStream, finally, we just take the bytearray of this OutputStream, creating an InputStream, which we can hand over to the Play Prompt step.

II. writing a prompt to a Windows share

First, install the JCIFS library, by following the steps 1 to 3 (including) of the previous section (I. reading a prompt from a Windows share).

1. Add these new variables:

  • exitCode, type int, initial value = 0;
  • mydoc, type Document, initial value null;
  • smbFileURL, type String; initial value = "";

2. Create a new script, add all the necessary steps, for example, Accept.

3. Add a new Set step. Assign the value of the smbFileURL variable, following this format:

smb://domain;user:password@ipaddress/share/file.wav

For example:

smb://ipcc;filereader:SuperS3crEt!@10.232.128.68/Temp/friday.wav

This  means: ipcc\filereader user with password SuperS3crEt! may read the  contents of the file friday.wav on the server 10.232.128.68 within the  Temp share.

For more possibilities, please read the JCIFS API docs, at  http://jcifs.samba.org/src/docs/api/jcifs/smb/SmbFile.html (scroll down to SMB URL Examples).

4. Add a new Recording step, that would yield the value of the mydoc variable. Use a prompt of your choice (may be something like "please record your message" etc)

5. Add a new Set step to the Successful recording branch of the previous (Recording) step. Use the variable exitCode. The value would be this closure:

{

java.io.OutputStream os = null;

java.io.InputStream in = null;

try {

int bufSize = 4096;

jcifs.smb.SmbFile smbFile = new jcifs.smb.SmbFile(smbFileURL);

os = smbFile.getOutputStream();

in  = mydoc.getInputStream();

byte[] bytesRead = new byte[bufSize];

int bytesReadLength = 0;

while ((bytesReadLength = in.read(bytesRead)) > 0 ) {

    os.write(bytesRead,0,bytesReadLength);

}

} catch (Exception e) {

return -1;

} finally {

in.close();

os.close();

return 0;

}

}

6. Save your script and test it. A new file, specified in the smbFileURL variable should be created within the Windows share, with the preferred format of UCCX (either G.711 uLaw or G.729 depending on the settings of your UCCX system).

Notice: the value of the exitCode variable will be -1 if, for any reason, an error happens during writing the prompt file. If it is written successfully, the value of the exitCode variable is 0.

Screenshot:

uccx_smbfilemagic_write.PNG

What just happened?

The Recording step created a new recording of type Document. This is just plain ordinary Java object, which is actually a string, or rather, a stream of bytes that equals to the prompt file contents. All we need to do is just create an inputstream of this object, and copy the contents of it to another stream, namely a FileOutputStream of the SMB File we create. The closure also has got an exception catching mechanism, if any exception is raised, it would give back the control to the script with the value -1 of the exitCode variable so you can react on it (instead of just having the script die which may be an embarrassement in most of the cases).

FAQ:

Q1. I'm getting an error in CCX Editor: "error unmarshalling return nested exception is java.net.SocketException". Why?

A1. Make sure you restart the CCX Engine after uploading the JCIFS library and before trying to run the script. Yes, it's really necessary.

Q2. Will Cisco TAC support this?

A2. I don't know, ask them :-) Probably not, since it uses an external library.

Q3. JCIFS is licensed under LGPL. Can it be used with UCCX?

A3. Not sure. I am not a lawyer. Probably yes. But again, I am not sure about it.

Comments
Beginner

i am doing the section I. [reading a prompt from a Windows share]

when I'm in step 8, add a new Set step (apply the code to byteArrayIS)

after I copied and paste the code to the value field, and clicked the APPLY in "Set" step

the Set step disappears itself in the IVR script. ...

I tried the testing on UCCX 8.0 with Script Editor 8.0 (WinXP)

and UCCX 8.5 with Script editor 8.5 (Win7)

however, both version got the same issue...

do you have any idea where I make the mistake ?

Thanks

Sam

Advocate

Hi,

this is a known defect with UCCX 8.0 - I don't remember the bug ID but I can look it up for you.

Anyway, please update your UCCX to the latest version and it'll work correctly.

G.

Beginner

Hi Gergely Szabo,

Thanks for the reply,

I'm now testing with UCCX8.5.1 and I found that the "set step disappear" because of the follow line

return new java.io.ByteArrayOutputStream(baos.toByteArray());

does it mean the set step not recognize / support the return type of ByteArrayOutputStream?

May I ask your development environment? (Java 1.6 and Windows 32bit platform)? I have no idea does it because of the development environment ...

Thanks

Sam

Advocate

Hi,

if it was not supported, it would tell you by throwing an error message at you. But it does not. It's a bug.

Again, make sure you've got the latest version of UCCX - go to CCO, check Downloads, grab the latest update for your UCCX, install it.

And make sure you're using the CCX Editor on the correct platform - I am not absolutely convinced Windows 7 is a supported operating system for the CCX Editor but I might be wrong. Again, just check the compatibility guide.

G.

Hi, I using read section in CCX 8.5 . I have validated the script correctly from CCX Editor, but whe I add new application and select the script then display the message : " An error ocurring while loading the script (Script[ScriptForo.aef]) Please check log for mor details".  I have been searching in the logs but I have seen anything.

Do you know what could be the problem?

Advocate

Hi,

can you post a screenshot? What is giving the error, the appadmin page?

G.

Hi,

I upload the screenshot with the error.

Yes, the error is showed in  appadmin page when I add a new applications and select the script.

Thanks in advance

Raúlerror-creating-app.jpg

Advocate

Hi,

hmm, no idea. If it validates alright, it should be alright.

Did you try the usual suspects, like restarting the UCCX, refreshing the scripts, etc?

Would it be possible to post the script so I can take a look at it?

G.

Hi

If it doesn't load, but does validate then it's often because the script contains a reference to a subflow that isn't valid.

Failing that you would need to look at the MIVR logs at the time that you select the script.

Regards

Aaron Harrison

Principal Engineer at Logicalis UK

Please rate helpful posts...

Hi Gergely,

I post a screenshot with the validation, and you can see the script an variables. I haven't option to upload the script.

Thanks in advance

Regards, Raul

validation-script-ok.png

Hi Aaron

I tryied search in MIVR logs some clue, but I didn't  find anything. Could you tell me what trace I should enable?

I have enabled in CCX ENGINE  app_mgr, script_mgr. Is it enoguht? or do you thind that I have enable other traces?

Thanks in advance

Regards, Raul

Hi All,

I have reboot the CCX and the problem has been solved.

Thank you for your  help

Regards, Raul

Beginner

I am not having anyluck writing the file out to one of our windows 2003 file server.

Where should I be looking in the logs to find out what I am doing wrong ?

variables.PNG

scritp.png

Then it goes off to a " I'm sorry message"  and no file is put on the server....

Beginner

I loaded the JAR file to the UCCX server with no problems. I did have to reboot the server in order to see the new variables Java.io.Input - Output - ETC....

Beginner

ok, so I got the file write to work after doing some upgrading. Which is great, now I need to have the file name be a variable so that I can save the filename based off of some inputs from the caller.  Any help would be great....

Thanks,

Will

CreatePlease to create content
Content for Community-Ad
Future of Work Virtual Summit Day 5

Cisco COVID-19 Survey