Old 04-12-2012, 04:27 PM   #1
KarlLai
Human being with feelings
 
KarlLai's Avatar
 
Join Date: Feb 2012
Posts: 26
Default About PCM_Source_CreateFromType("MIDI")...

Hi,

I am trying to create multiple takes with multiple midi sources in a track with C++ codes, like this:

Code:
  // add a media item
  MediaItem* newMediaItem = AddMediaItemToTrack(newReaperTrack);
  GetSetMediaItemInfo(newMediaItem, "D_POSITION", &startTime);
  GetSetMediaItemInfo(newMediaItem, "D_LENGTH", &length);

  PCM_source* newSource = PCM_Source_CreateFromType("MIDI");

  // add a take
  MediaItem_Take* newTake = AddTakeToMediaItem(newMediaItem);
  GetSetMediaItemTakeInfo(newTake, "P_NAME", (void*)name);
  GetSetMediaItemTakeInfo(newTake, "P_SOURCE", (void*)newSource);
  GetSetMediaItemTakeInfo(newTake, "D_STARTOFFS", &startTime);
After I compiled the codes and put the plugin in reaper, it did create a new media item. However, there is a weird string of "offline" in the middle of that media item, and I cannot open it with the midi editor.

What does that mean? How do I fix it?

Also, when I search in SWS codes, there is only one place that use PCM_Source_CreateFromType(), and it's commented out. The comment says, "JFB!!! commented: generating evts from scratch does not work, unfortunately.. nailed it down to PCM_Source_CreateFromType("MIDI") which seems to be KO (?)". Does that mean this API function is not even working properly?

Thank you.

Last edited by KarlLai; 04-17-2012 at 02:12 PM.
KarlLai is offline   Reply With Quote
Old 04-17-2012, 05:28 AM   #2
schwa
Administrator
 
schwa's Avatar
 
Join Date: Mar 2007
Location: location, location
Posts: 7,673
Default

There is another undocumented step needed to initialize the state of the MIDI source. For ease of use, we will add a new API function in the next REAPER prerelease build:

Code:
MediaItem* CreateNewMIDIItemInProj(double starttime, double endtime);
schwa is offline   Reply With Quote
Old 04-17-2012, 10:31 AM   #3
KarlLai
Human being with feelings
 
KarlLai's Avatar
 
Join Date: Feb 2012
Posts: 26
Default

Quote:
Originally Posted by schwa View Post
There is another undocumented step needed to initialize the state of the MIDI source. For ease of use, we will add a new API function in the next REAPER prerelease build:

Code:
MediaItem* CreateNewMIDIItemInProj(double starttime, double endtime);
Thank you

For now, should I just wait for the new API or there is a way to initialize the state properly?
KarlLai is offline   Reply With Quote
Old 04-17-2012, 11:16 AM   #4
schwa
Administrator
 
schwa's Avatar
 
Join Date: Mar 2007
Location: location, location
Posts: 7,673
Default

The new API function is in the latest REAPER prerelease version.

http://forum.cockos.com/showthread.php?t=22836
schwa is offline   Reply With Quote
Old 04-17-2012, 11:39 AM   #5
KarlLai
Human being with feelings
 
KarlLai's Avatar
 
Join Date: Feb 2012
Posts: 26
Default

Quote:
Originally Posted by schwa View Post
The new API function is in the latest REAPER prerelease version.

http://forum.cockos.com/showthread.php?t=22836
COOL! Thanks a lot
KarlLai is offline   Reply With Quote
Old 04-17-2012, 01:52 PM   #6
KarlLai
Human being with feelings
 
KarlLai's Avatar
 
Join Date: Feb 2012
Posts: 26
Default

Quote:
Originally Posted by schwa View Post
The new API function is in the latest REAPER prerelease version.

http://forum.cockos.com/showthread.php?t=22836
Sorry but another question... What is the proper way to link this new midi item to a track? Is MoveMediaItemToTrack() the right one?

Last edited by KarlLai; 04-17-2012 at 02:02 PM.
KarlLai is offline   Reply With Quote
Old 04-27-2012, 06:58 AM   #7
schwa
Administrator
 
schwa's Avatar
 
Join Date: Mar 2007
Location: location, location
Posts: 7,673
Default

Oh, you wanted to add the MIDI item to a track? <ahem>

We will change the new API function to take a MediaTrack parameter as well.
schwa is offline   Reply With Quote
Old 04-30-2012, 06:46 PM   #8
KarlLai
Human being with feelings
 
KarlLai's Avatar
 
Join Date: Feb 2012
Posts: 26
Default

Quote:
Originally Posted by schwa View Post
Oh, you wanted to add the MIDI item to a track? <ahem>

We will change the new API function to take a MediaTrack parameter as well.
Thank you! When will the next version/pre-version be released?
KarlLai is offline   Reply With Quote
Old 05-02-2012, 05:17 PM   #9
KarlLai
Human being with feelings
 
KarlLai's Avatar
 
Join Date: Feb 2012
Posts: 26
Default

Quote:
Originally Posted by KarlLai View Post
Thank you! When will the next version/pre-version be released?
Sad... There is no change in pre7......
KarlLai is offline   Reply With Quote
Old 05-02-2012, 06:03 PM   #10
Banned
Human being with feelings
 
Banned's Avatar
 
Join Date: Mar 2008
Location: Unwired (probably in the proximity of Amsterdam)
Posts: 3,698
Default

Quote:
Originally Posted by KarlLai View Post
Sad... There is no change in pre7......
I figured it was related to this?
Quote:
Originally Posted by musicbynumbers View Post
4.23pre7 - May 2 2012
[...]
+ API: CreateNewMIDIItemInProject now takes a track parameter
[...]
__________________
˙lɐd 'ʎɐʍ ƃuoɹʍ ǝɥʇ ǝɔıʌǝp ʇɐɥʇ ƃuıploɥ ǝɹ,noʎ
Banned is offline   Reply With Quote
Old 05-06-2012, 07:26 AM   #11
Jeffos
Mortal
 
Jeffos's Avatar
 
Join Date: Dec 2008
Location: France
Posts: 1,719
Default

Quote:
Originally Posted by KarlLai View Post
Sad... There is no change in pre7......
The generated .h is not up-to-date but the func is indeed there. It will work if you redefine it as:
Code:
REAPERAPI_DECL MediaItem* (*CreateNewMIDIItemInProj)(MediaTrack* track, double starttime, double endtime);
Quote:
Originally Posted by KarlLai View Post
commented: generating evts from scratch does not work, unfortunately.. nailed it down to PCM_Source_CreateFromType("MIDI") which seems to be KO (?)
This comment is from me. I workarounded that but I would like to know that "undocumented step needed to initialize the state of the MIDI source" schwa talked about! Note: in my case I just want to create a PCM_source from scratch and fill it with midi_realtime_write_struct_t (I do not plan to insert it as take/item the arrange).
Jeffos is offline   Reply With Quote
Old 05-07-2012, 04:47 PM   #12
KarlLai
Human being with feelings
 
KarlLai's Avatar
 
Join Date: Feb 2012
Posts: 26
Default

@Jeffos: Thank you for letting me know! Yeah I should also check the update notes.

What I am doing is: I want to create a track, create a media item, and then insert midi events into the media item. For now I just create a simple and empty midi file at runtime and call PCM_Source_CreateFromFile(). It works but it's totally a hack.

I will try the new API after the next stable version is out, since my customer are not using the pre versions at their work
KarlLai is offline   Reply With Quote
Old 06-11-2012, 05:01 AM   #13
drew
Mobile
 
drew's Avatar
 
Join Date: Jan 2006
Location: London & São Paulo. Hardcore commercial REAPERite
Posts: 1,575
Default

Just to check on the latest situation re MIDI take creation on the fly, am I right to say it is still not possible to alter the textual state of an item or individual take in the way that we can change track state?

I managed to get CreateNewMIDIItemInProj working in ReaScript by changing that definition in reaper_python.py from
Code:
a=_ft['CreateNewMIDIItemInProj']
  f=CFUNCTYPE(c_uint64,c_double,c_double)(a)
  t=(c_double(p0),c_double(p1))
  r=f(t[0],t[1])
to
Code:
a=_ft['CreateNewMIDIItemInProj']
  f=CFUNCTYPE(c_uint64,c_uint64,c_double,c_double)(a)
  t=(rpr_packp('MediaTrack*',p0),c_double(p1),c_double(p2))
  r=f(t[0],t[1],t[2])
As a result it now works with the updated version of the schwa's call (the one which starts with MediaTrack parameter), but there still doesn't seem to be a way to write MIDI events to it in ReaScript.

Could there either be a call to trigger a new live item state after setting it using the existing GetSetItemState call, or maybe something on a per-take basis like a P_SOURCEMIDI call that could be read & written with GetSetMediaItemTakeInfo_String to allow us to write/overwrite MIDI data?

Thanks

Drew
__________________
Proudly using REAPER exclusively for professional music production at Qsonics.com and recording broadcast and narrative voiceovers at DrewWhite.com.
drew is offline   Reply With Quote
Old 08-28-2012, 01:17 PM   #14
drew
Mobile
 
drew's Avatar
 
Join Date: Jan 2006
Location: London & São Paulo. Hardcore commercial REAPERite
Posts: 1,575
Default

a little bumpity... does anyone have any info on how to write the state of a MIDI take/item? This CreateNewMIDIItemInProj call (which still shows as only start & end time parameters in ReaScript help, by the way) allows me to create the 'container' but not populate it with any MIDI data.

At the moment I'm creating a dummy track with an item (by writing track state) and then moving the item, before deleting that track - but this is quite a workaround!

Thanks

Drew
__________________
Proudly using REAPER exclusively for professional music production at Qsonics.com and recording broadcast and narrative voiceovers at DrewWhite.com.
drew is offline   Reply With Quote
Old 08-30-2012, 12:45 PM   #15
Jeffos
Mortal
 
Jeffos's Avatar
 
Join Date: Dec 2008
Location: France
Posts: 1,719
Default

About the original issue/OP (i.e. PCM_Source_CreateFromType and how to generate MIDI events from scratch): I sorted this out thanks to the little clue schwa has posted above..
Quote:
Originally Posted by schwa View Post
There is another undocumented step needed to initialize the state of the MIDI source.
.. which I translated into C like (note_on+note_off example here):
Code:
PCM_source* src = NULL;
const char* state = "HASDATA 1 960 QN\nE 90 90 3d 60\nE 120 80 3d 00\n\nE 1 b1 7b 00\nIGNTEMPO 0 120.00000000 4 4\n>\n"; // <--- make sure the last MIDI evt is a (dummy) CC123!
int len = strlen(state);
WDL_HeapBuf hb;
void* p = hb.Resize(len, false);
if (p && hb.GetSize()==len)
{
  if (src = PCM_Source_CreateFromType("MIDI"))
  {
    memcpy(p, state, len);
    ProjectStateContext* ctx = ProjectCreateMemCtx(&hb);
    if (src->LoadState("<SOURCE MIDI\n", ctx) < 0)
      DELETE_NULL(src);
    delete ctx;
  }
}
Works great The PCM_source can then also be processed with midi_realtime_write_struct_t, etc.. (w/o having to add it to the arrange, i.e. w/o using the new CreateNewMIDIItemInProj)

___________

Hey Drew,
Quote:
does anyone have any info on how to write the state of a MIDI take/item?
this is no big deal in C but I guess you are talking of ReaScript here (?) If so, check out gofer's thread about that: http://forum.cockos.com/showthread.php?t=85951 (w/ a limitation I posted there)
Quote:
This CreateNewMIDIItemInProj call [...] allows me to create the 'container' but not populate it with any MIDI data.
may be you should post the code?
Jeffos is offline   Reply With Quote
Old 08-31-2012, 05:16 AM   #16
drew
Mobile
 
drew's Avatar
 
Join Date: Jan 2006
Location: London & São Paulo. Hardcore commercial REAPERite
Posts: 1,575
Default

Thanks for all the info Jeffos. It looks like I've solved my ReaScript issue.

I've given up trying to use the CreateNewMIDIItemInProj call, which seems to cause errors (and what is a MIDI item anyway? I thought there were only "MIDI takes" in REAPER!)

So here is the working code I use to generate a new item with MIDI take:
Code:
__author__ = 'DREQ'
ScriptName = "MIDI generation test"

from reaper_python import *

MaxStateLen = (1024**2*4)

RPR_InsertTrackAtIndex(0,True)
NewTrack=RPR_GetTrack(0,0)

#why does this return 4 rather than the value shown in the INI for the variable of this name? (eg. 960 by default)
ticks=RPR_get_config_var("miditicksperbeat",0)[2]

#override with default until I find out!
ticks=960


Measure1Start=float(RPR_TimeMap2_beatsToTime(0,0,1)[0])
Measure2Start=float(RPR_TimeMap2_beatsToTime(0,0,2)[0])

NewItem=RPR_AddMediaItemToTrack(NewTrack)
RPR_SetMediaItemInfo_Value(NewItem,"D_POSITION",Measure1Start)
RPR_SetMediaItemInfo_Value(NewItem,"D_LENGTH",Measure2Start-Measure1Start)
NewTake=RPR_AddTakeToMediaItem(NewItem)

state=RPR_GetSetItemState2(NewItem,"",MaxStateLen,False)[2]

timesig_num=RPR_GetProjectTimeSignature2(0,0,0)[2]

allthis="<SOURCE MIDI\n"
allthis+="HASDATA 1 " + str(ticks) + " QN\n"
allthis+="E " + str(int(ticks*1)) + " 90 20 7f\n" #start a note at 1.2
allthis+="E " + str(int(ticks*1)) + " 80 20 7f\n" #end a note at 1.3
allthis+="E " + str(int(ticks*timesig_num)) + " b0 7b 00\n" #places data end marker 1 measure after last note
allthis+=">" #no new line at end

statelist=state.split("\n")
for idx,thisline in enumerate(statelist):
	if thisline.startswith("<SOURCE EMPTY"):
		statelist[idx]=allthis
		statelist.pop(idx+1)

state='\n'.join(statelist)

RPR_GetSetItemState2(NewItem,state,MaxStateLen,False)
I can confirm that targetting an existing item also works.. eg. replacing the <SOURCE MIDI > block

Now I just need to solve the mystery of why "miditicksperbeat" config var gives me 4 rather than 960, which is the value in the INI! If there is another way to get the default MIDI ticks per beat that would be handy to know.
__________________
Proudly using REAPER exclusively for professional music production at Qsonics.com and recording broadcast and narrative voiceovers at DrewWhite.com.
drew is offline   Reply With Quote
Reply

Tags
c++, midi

Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump


All times are GMT -7. The time now is 10:48 AM.


Powered by vBulletin® Version 3.8.4
Copyright ©2000 - 2014, Jelsoft Enterprises Ltd.