pa_win_wdmks.c 229 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764376537663767376837693770377137723773377437753776377737783779378037813782378337843785378637873788378937903791379237933794379537963797379837993800380138023803380438053806380738083809381038113812381338143815381638173818381938203821382238233824382538263827382838293830383138323833383438353836383738383839384038413842384338443845384638473848384938503851385238533854385538563857385838593860386138623863386438653866386738683869387038713872387338743875387638773878387938803881388238833884388538863887388838893890389138923893389438953896389738983899390039013902390339043905390639073908390939103911391239133914391539163917391839193920392139223923392439253926392739283929393039313932393339343935393639373938393939403941394239433944394539463947394839493950395139523953395439553956395739583959396039613962396339643965396639673968396939703971397239733974397539763977397839793980398139823983398439853986398739883989399039913992399339943995399639973998399940004001400240034004400540064007400840094010401140124013401440154016401740184019402040214022402340244025402640274028402940304031403240334034403540364037403840394040404140424043404440454046404740484049405040514052405340544055405640574058405940604061406240634064406540664067406840694070407140724073407440754076407740784079408040814082408340844085408640874088408940904091409240934094409540964097409840994100410141024103410441054106410741084109411041114112411341144115411641174118411941204121412241234124412541264127412841294130413141324133413441354136413741384139414041414142414341444145414641474148414941504151415241534154415541564157415841594160416141624163416441654166416741684169417041714172417341744175417641774178417941804181418241834184418541864187418841894190419141924193419441954196419741984199420042014202420342044205420642074208420942104211421242134214421542164217421842194220422142224223422442254226422742284229423042314232423342344235423642374238423942404241424242434244424542464247424842494250425142524253425442554256425742584259426042614262426342644265426642674268426942704271427242734274427542764277427842794280428142824283428442854286428742884289429042914292429342944295429642974298429943004301430243034304430543064307430843094310431143124313431443154316431743184319432043214322432343244325432643274328432943304331433243334334433543364337433843394340434143424343434443454346434743484349435043514352435343544355435643574358435943604361436243634364436543664367436843694370437143724373437443754376437743784379438043814382438343844385438643874388438943904391439243934394439543964397439843994400440144024403440444054406440744084409441044114412441344144415441644174418441944204421442244234424442544264427442844294430443144324433443444354436443744384439444044414442444344444445444644474448444944504451445244534454445544564457445844594460446144624463446444654466446744684469447044714472447344744475447644774478447944804481448244834484448544864487448844894490449144924493449444954496449744984499450045014502450345044505450645074508450945104511451245134514451545164517451845194520452145224523452445254526452745284529453045314532453345344535453645374538453945404541454245434544454545464547454845494550455145524553455445554556455745584559456045614562456345644565456645674568456945704571457245734574457545764577457845794580458145824583458445854586458745884589459045914592459345944595459645974598459946004601460246034604460546064607460846094610461146124613461446154616461746184619462046214622462346244625462646274628462946304631463246334634463546364637463846394640464146424643464446454646464746484649465046514652465346544655465646574658465946604661466246634664466546664667466846694670467146724673467446754676467746784679468046814682468346844685468646874688468946904691469246934694469546964697469846994700470147024703470447054706470747084709471047114712471347144715471647174718471947204721472247234724472547264727472847294730473147324733473447354736473747384739474047414742474347444745474647474748474947504751475247534754475547564757475847594760476147624763476447654766476747684769477047714772477347744775477647774778477947804781478247834784478547864787478847894790479147924793479447954796479747984799480048014802480348044805480648074808480948104811481248134814481548164817481848194820482148224823482448254826482748284829483048314832483348344835483648374838483948404841484248434844484548464847484848494850485148524853485448554856485748584859486048614862486348644865486648674868486948704871487248734874487548764877487848794880488148824883488448854886488748884889489048914892489348944895489648974898489949004901490249034904490549064907490849094910491149124913491449154916491749184919492049214922492349244925492649274928492949304931493249334934493549364937493849394940494149424943494449454946494749484949495049514952495349544955495649574958495949604961496249634964496549664967496849694970497149724973497449754976497749784979498049814982498349844985498649874988498949904991499249934994499549964997499849995000500150025003500450055006500750085009501050115012501350145015501650175018501950205021502250235024502550265027502850295030503150325033503450355036503750385039504050415042504350445045504650475048504950505051505250535054505550565057505850595060506150625063506450655066506750685069507050715072507350745075507650775078507950805081508250835084508550865087508850895090509150925093509450955096509750985099510051015102510351045105510651075108510951105111511251135114511551165117511851195120512151225123512451255126512751285129513051315132513351345135513651375138513951405141514251435144514551465147514851495150515151525153515451555156515751585159516051615162516351645165516651675168516951705171517251735174517551765177517851795180518151825183518451855186518751885189519051915192519351945195519651975198519952005201520252035204520552065207520852095210521152125213521452155216521752185219522052215222522352245225522652275228522952305231523252335234523552365237523852395240524152425243524452455246524752485249525052515252525352545255525652575258525952605261526252635264526552665267526852695270527152725273527452755276527752785279528052815282528352845285528652875288528952905291529252935294529552965297529852995300530153025303530453055306530753085309531053115312531353145315531653175318531953205321532253235324532553265327532853295330533153325333533453355336533753385339534053415342534353445345534653475348534953505351535253535354535553565357535853595360536153625363536453655366536753685369537053715372537353745375537653775378537953805381538253835384538553865387538853895390539153925393539453955396539753985399540054015402540354045405540654075408540954105411541254135414541554165417541854195420542154225423542454255426542754285429543054315432543354345435543654375438543954405441544254435444544554465447544854495450545154525453545454555456545754585459546054615462546354645465546654675468546954705471547254735474547554765477547854795480548154825483548454855486548754885489549054915492549354945495549654975498549955005501550255035504550555065507550855095510551155125513551455155516551755185519552055215522552355245525552655275528552955305531553255335534553555365537553855395540554155425543554455455546554755485549555055515552555355545555555655575558555955605561556255635564556555665567556855695570557155725573557455755576557755785579558055815582558355845585558655875588558955905591559255935594559555965597559855995600560156025603560456055606560756085609561056115612561356145615561656175618561956205621562256235624562556265627562856295630563156325633563456355636563756385639564056415642564356445645564656475648564956505651565256535654565556565657565856595660566156625663566456655666566756685669567056715672567356745675567656775678567956805681568256835684568556865687568856895690569156925693569456955696569756985699570057015702570357045705570657075708570957105711571257135714571557165717571857195720572157225723572457255726572757285729573057315732573357345735573657375738573957405741574257435744574557465747574857495750575157525753575457555756575757585759576057615762576357645765576657675768576957705771577257735774577557765777577857795780578157825783578457855786578757885789579057915792579357945795579657975798579958005801580258035804580558065807580858095810581158125813581458155816581758185819582058215822582358245825582658275828582958305831583258335834583558365837583858395840584158425843584458455846584758485849585058515852585358545855585658575858585958605861586258635864586558665867586858695870587158725873587458755876587758785879588058815882588358845885588658875888588958905891589258935894589558965897589858995900590159025903590459055906590759085909591059115912591359145915591659175918591959205921592259235924592559265927592859295930593159325933593459355936593759385939594059415942594359445945594659475948594959505951595259535954595559565957595859595960596159625963596459655966596759685969597059715972597359745975597659775978597959805981598259835984598559865987598859895990599159925993599459955996599759985999600060016002600360046005600660076008600960106011601260136014601560166017601860196020602160226023602460256026602760286029603060316032603360346035603660376038603960406041604260436044604560466047604860496050605160526053605460556056605760586059606060616062606360646065606660676068606960706071607260736074607560766077607860796080608160826083608460856086608760886089609060916092609360946095609660976098609961006101610261036104610561066107610861096110611161126113611461156116611761186119612061216122612361246125612661276128612961306131613261336134613561366137613861396140614161426143614461456146614761486149615061516152615361546155615661576158615961606161616261636164616561666167616861696170617161726173617461756176617761786179618061816182618361846185618661876188618961906191619261936194619561966197619861996200620162026203620462056206620762086209621062116212621362146215621662176218621962206221622262236224622562266227622862296230623162326233623462356236623762386239624062416242624362446245624662476248624962506251625262536254625562566257625862596260626162626263626462656266626762686269627062716272627362746275627662776278627962806281628262836284628562866287628862896290629162926293629462956296629762986299630063016302630363046305630663076308630963106311631263136314631563166317631863196320632163226323632463256326632763286329633063316332633363346335633663376338633963406341634263436344634563466347634863496350635163526353635463556356635763586359636063616362636363646365636663676368636963706371637263736374637563766377637863796380638163826383638463856386638763886389639063916392639363946395639663976398639964006401640264036404640564066407640864096410641164126413641464156416641764186419642064216422642364246425642664276428642964306431643264336434643564366437643864396440644164426443644464456446644764486449645064516452645364546455645664576458645964606461646264636464646564666467646864696470647164726473647464756476647764786479648064816482648364846485648664876488648964906491649264936494649564966497649864996500650165026503650465056506650765086509651065116512651365146515651665176518651965206521652265236524652565266527652865296530653165326533653465356536653765386539654065416542654365446545654665476548654965506551655265536554655565566557655865596560656165626563656465656566656765686569657065716572657365746575657665776578657965806581658265836584658565866587658865896590659165926593659465956596659765986599660066016602660366046605660666076608660966106611661266136614661566166617661866196620662166226623662466256626662766286629663066316632663366346635663666376638663966406641664266436644664566466647664866496650665166526653665466556656
  1. /*
  2. * $Id: pa_win_wdmks.c 1885 2012-12-28 16:54:25Z robiwan $
  3. * PortAudio Windows WDM-KS interface
  4. *
  5. * Author: Andrew Baldwin, Robert Bielik (WaveRT)
  6. * Based on the Open Source API proposed by Ross Bencina
  7. * Copyright (c) 1999-2004 Andrew Baldwin, Ross Bencina, Phil Burk
  8. *
  9. * Permission is hereby granted, free of charge, to any person obtaining
  10. * a copy of this software and associated documentation files
  11. * (the "Software"), to deal in the Software without restriction,
  12. * including without limitation the rights to use, copy, modify, merge,
  13. * publish, distribute, sublicense, and/or sell copies of the Software,
  14. * and to permit persons to whom the Software is furnished to do so,
  15. * subject to the following conditions:
  16. *
  17. * The above copyright notice and this permission notice shall be
  18. * included in all copies or substantial portions of the Software.
  19. *
  20. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  21. * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  22. * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
  23. * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
  24. * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
  25. * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  26. * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  27. */
  28. /*
  29. * The text above constitutes the entire PortAudio license; however,
  30. * the PortAudio community also makes the following non-binding requests:
  31. *
  32. * Any person wishing to distribute modifications to the Software is
  33. * requested to send the modifications to the original developer so that
  34. * they can be incorporated into the canonical version. It is also
  35. * requested that these non-binding requests be included along with the
  36. * license above.
  37. */
  38. /** @file
  39. @ingroup hostapi_src
  40. @brief Portaudio WDM-KS host API.
  41. @note This is the implementation of the Portaudio host API using the
  42. Windows WDM/Kernel Streaming API in order to enable very low latency
  43. playback and recording on all modern Windows platforms (e.g. 2K, XP, Vista, Win7)
  44. Note: This API accesses the device drivers below the usual KMIXER
  45. component which is normally used to enable multi-client mixing and
  46. format conversion. That means that it will lock out all other users
  47. of a device for the duration of active stream using those devices
  48. */
  49. #include <stdio.h>
  50. #if (defined(_WIN32) && (defined(_MSC_VER) && (_MSC_VER >= 1200))) /* MSC version 6 and above */
  51. #pragma comment( lib, "setupapi.lib" )
  52. #endif
  53. /* Debugging/tracing support */
  54. #define PA_LOGE_
  55. #define PA_LOGL_
  56. #ifdef __GNUC__
  57. #include <initguid.h>
  58. #define _WIN32_WINNT 0x0501
  59. #define WINVER 0x0501
  60. #endif
  61. #include <string.h> /* strlen() */
  62. #include <assert.h>
  63. #include <wchar.h> /* iswspace() */
  64. #include "pa_util.h"
  65. #include "pa_allocation.h"
  66. #include "pa_hostapi.h"
  67. #include "pa_stream.h"
  68. #include "pa_cpuload.h"
  69. #include "pa_process.h"
  70. #include "portaudio.h"
  71. #include "pa_debugprint.h"
  72. #include "pa_memorybarrier.h"
  73. #include "pa_ringbuffer.h"
  74. #include "pa_trace.h"
  75. #include "pa_win_waveformat.h"
  76. #include "pa_win_wdmks.h"
  77. #include <windows.h>
  78. #include <winioctl.h>
  79. #include <process.h>
  80. #include <math.h>
  81. #ifdef _MSC_VER
  82. #define snprintf _snprintf
  83. #define vsnprintf _vsnprintf
  84. #endif
  85. /* The PA_HP_TRACE macro is used in RT parts, so it can be switched off without affecting
  86. the rest of the debug tracing */
  87. #if 1
  88. #define PA_HP_TRACE(x) PaUtil_AddHighSpeedLogMessage x ;
  89. #else
  90. #define PA_HP_TRACE(x)
  91. #endif
  92. /* A define that selects whether the resulting pin names are chosen from pin category
  93. instead of the available pin names, who sometimes can be quite cheesy, like "Volume control".
  94. Default is to use the pin category.
  95. */
  96. #ifndef PA_WDMKS_USE_CATEGORY_FOR_PIN_NAMES
  97. #define PA_WDMKS_USE_CATEGORY_FOR_PIN_NAMES 1
  98. #endif
  99. #ifdef __GNUC__
  100. #undef PA_LOGE_
  101. #define PA_LOGE_ PA_DEBUG(("%s {\n",__FUNCTION__))
  102. #undef PA_LOGL_
  103. #define PA_LOGL_ PA_DEBUG(("} %s\n",__FUNCTION__))
  104. /* These defines are set in order to allow the WIndows DirectX
  105. * headers to compile with a GCC compiler such as MinGW
  106. * NOTE: The headers may generate a few warning in GCC, but
  107. * they should compile */
  108. #define _INC_MMSYSTEM
  109. #define _INC_MMREG
  110. #define _NTRTL_ /* Turn off default definition of DEFINE_GUIDEX */
  111. #define DEFINE_GUID_THUNK(name,guid) DEFINE_GUID(name,guid)
  112. #define DEFINE_GUIDEX(n) DEFINE_GUID_THUNK( n, STATIC_##n )
  113. #if !defined( DEFINE_WAVEFORMATEX_GUID )
  114. #define DEFINE_WAVEFORMATEX_GUID(x) (USHORT)(x), 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71
  115. #endif
  116. #define WAVE_FORMAT_ADPCM 0x0002
  117. #define WAVE_FORMAT_IEEE_FLOAT 0x0003
  118. #define WAVE_FORMAT_ALAW 0x0006
  119. #define WAVE_FORMAT_MULAW 0x0007
  120. #define WAVE_FORMAT_MPEG 0x0050
  121. #define WAVE_FORMAT_DRM 0x0009
  122. #define DYNAMIC_GUID_THUNK(l,w1,w2,b1,b2,b3,b4,b5,b6,b7,b8) {l,w1,w2,{b1,b2,b3,b4,b5,b6,b7,b8}}
  123. #define DYNAMIC_GUID(data) DYNAMIC_GUID_THUNK(data)
  124. #endif
  125. /* use CreateThread for CYGWIN/Windows Mobile, _beginthreadex for all others */
  126. #if !defined(__CYGWIN__) && !defined(_WIN32_WCE)
  127. #define CREATE_THREAD_FUNCTION (HANDLE)_beginthreadex
  128. #define PA_THREAD_FUNC static unsigned WINAPI
  129. #else
  130. #define CREATE_THREAD_FUNCTION CreateThread
  131. #define PA_THREAD_FUNC static DWORD WINAPI
  132. #endif
  133. #ifdef _MSC_VER
  134. #define NOMMIDS
  135. #define DYNAMIC_GUID(data) {data}
  136. #define _NTRTL_ /* Turn off default definition of DEFINE_GUIDEX */
  137. #undef DEFINE_GUID
  138. #define DEFINE_GUID(n,data) EXTERN_C const GUID n = {data}
  139. #define DEFINE_GUID_THUNK(n,data) DEFINE_GUID(n,data)
  140. #define DEFINE_GUIDEX(n) DEFINE_GUID_THUNK(n, STATIC_##n)
  141. #endif
  142. #include <setupapi.h>
  143. #ifndef EXTERN_C
  144. #define EXTERN_C extern
  145. #endif
  146. #if defined(__GNUC__)
  147. /* For MinGW we reference mingw-include files supplied with WASAPI */
  148. #define WINBOOL BOOL
  149. #include "../wasapi/mingw-include/ks.h"
  150. #include "../wasapi/mingw-include/ksmedia.h"
  151. #else
  152. #include <mmreg.h>
  153. #include <ks.h>
  154. /* Note that Windows SDK V6.0A or later is needed for WaveRT specific structs to be present in
  155. ksmedia.h. Also make sure that the SDK include path is before other include paths (that may contain
  156. an "old" ksmedia.h), so the proper ksmedia.h is used */
  157. #include <ksmedia.h>
  158. #endif
  159. #include <assert.h>
  160. #include <stdio.h>
  161. /* These next definitions allow the use of the KSUSER DLL */
  162. typedef /*KSDDKAPI*/ DWORD WINAPI KSCREATEPIN(HANDLE, PKSPIN_CONNECT, ACCESS_MASK, PHANDLE);
  163. extern HMODULE DllKsUser;
  164. extern KSCREATEPIN* FunctionKsCreatePin;
  165. /* These definitions allows the use of AVRT.DLL on Vista and later OSs */
  166. typedef enum _PA_AVRT_PRIORITY
  167. {
  168. PA_AVRT_PRIORITY_LOW = -1,
  169. PA_AVRT_PRIORITY_NORMAL,
  170. PA_AVRT_PRIORITY_HIGH,
  171. PA_AVRT_PRIORITY_CRITICAL
  172. } PA_AVRT_PRIORITY, *PPA_AVRT_PRIORITY;
  173. typedef struct
  174. {
  175. HINSTANCE hInstance;
  176. HANDLE (WINAPI *AvSetMmThreadCharacteristics) (LPCSTR, LPDWORD);
  177. BOOL (WINAPI *AvRevertMmThreadCharacteristics) (HANDLE);
  178. BOOL (WINAPI *AvSetMmThreadPriority) (HANDLE, PA_AVRT_PRIORITY);
  179. } PaWinWDMKSAvRtEntryPoints;
  180. static PaWinWDMKSAvRtEntryPoints paWinWDMKSAvRtEntryPoints = {0};
  181. /* An unspecified channel count (-1) is not treated correctly, so we replace it with
  182. * an arbitrarily large number */
  183. #define MAXIMUM_NUMBER_OF_CHANNELS 256
  184. /* Forward definition to break circular type reference between pin and filter */
  185. struct __PaWinWdmFilter;
  186. typedef struct __PaWinWdmFilter PaWinWdmFilter;
  187. struct __PaWinWdmPin;
  188. typedef struct __PaWinWdmPin PaWinWdmPin;
  189. struct __PaWinWdmStream;
  190. typedef struct __PaWinWdmStream PaWinWdmStream;
  191. /* Function prototype for getting audio position */
  192. typedef PaError (*FunctionGetPinAudioPosition)(PaWinWdmPin*, unsigned long*);
  193. /* Function prototype for memory barrier */
  194. typedef void (*FunctionMemoryBarrier)(void);
  195. struct __PaProcessThreadInfo;
  196. typedef struct __PaProcessThreadInfo PaProcessThreadInfo;
  197. typedef PaError (*FunctionPinHandler)(PaProcessThreadInfo* pInfo, unsigned eventIndex);
  198. typedef enum __PaStreamStartEnum
  199. {
  200. StreamStart_kOk,
  201. StreamStart_kFailed,
  202. StreamStart_kCnt
  203. } PaStreamStartEnum;
  204. /* Multiplexed input structure.
  205. * Very often several physical inputs are multiplexed through a MUX node (represented in the topology filter) */
  206. typedef struct __PaWinWdmMuxedInput
  207. {
  208. wchar_t friendlyName[MAX_PATH];
  209. ULONG muxPinId;
  210. ULONG muxNodeId;
  211. ULONG endpointPinId;
  212. } PaWinWdmMuxedInput;
  213. /* The Pin structure
  214. * A pin is an input or output node, e.g. for audio flow */
  215. struct __PaWinWdmPin
  216. {
  217. HANDLE handle;
  218. PaWinWdmMuxedInput** inputs;
  219. unsigned inputCount;
  220. wchar_t friendlyName[MAX_PATH];
  221. PaWinWdmFilter* parentFilter;
  222. PaWDMKSSubType pinKsSubType;
  223. unsigned long pinId;
  224. unsigned long endpointPinId; /* For output pins */
  225. KSPIN_CONNECT* pinConnect;
  226. unsigned long pinConnectSize;
  227. KSDATAFORMAT_WAVEFORMATEX* ksDataFormatWfx;
  228. KSPIN_COMMUNICATION communication;
  229. KSDATARANGE* dataRanges;
  230. KSMULTIPLE_ITEM* dataRangesItem;
  231. KSPIN_DATAFLOW dataFlow;
  232. KSPIN_CINSTANCES instances;
  233. unsigned long frameSize;
  234. int maxChannels;
  235. unsigned long formats;
  236. int defaultSampleRate;
  237. ULONG *positionRegister; /* WaveRT */
  238. ULONG hwLatency; /* WaveRT */
  239. FunctionMemoryBarrier fnMemBarrier; /* WaveRT */
  240. FunctionGetPinAudioPosition fnAudioPosition; /* WaveRT */
  241. FunctionPinHandler fnEventHandler;
  242. FunctionPinHandler fnSubmitHandler;
  243. };
  244. /* The Filter structure
  245. * A filter has a number of pins and a "friendly name" */
  246. struct __PaWinWdmFilter
  247. {
  248. HANDLE handle;
  249. PaWinWDMKSDeviceInfo devInfo; /* This will hold information that is exposed in PaDeviceInfo */
  250. DWORD deviceNode;
  251. int pinCount;
  252. PaWinWdmPin** pins;
  253. PaWinWdmFilter* topologyFilter;
  254. wchar_t friendlyName[MAX_PATH];
  255. int validPinCount;
  256. int usageCount;
  257. KSMULTIPLE_ITEM* connections;
  258. KSMULTIPLE_ITEM* nodes;
  259. int filterRefCount;
  260. };
  261. typedef struct __PaWinWdmDeviceInfo
  262. {
  263. PaDeviceInfo inheritedDeviceInfo;
  264. char compositeName[MAX_PATH]; /* Composite name consists of pin name + device name in utf8 */
  265. PaWinWdmFilter* filter;
  266. unsigned long pin;
  267. int muxPosition; /* Used only for input devices */
  268. int endpointPinId;
  269. }
  270. PaWinWdmDeviceInfo;
  271. /* PaWinWdmHostApiRepresentation - host api datastructure specific to this implementation */
  272. typedef struct __PaWinWdmHostApiRepresentation
  273. {
  274. PaUtilHostApiRepresentation inheritedHostApiRep;
  275. PaUtilStreamInterface callbackStreamInterface;
  276. PaUtilStreamInterface blockingStreamInterface;
  277. PaUtilAllocationGroup* allocations;
  278. int deviceCount;
  279. }
  280. PaWinWdmHostApiRepresentation;
  281. typedef struct __DATAPACKET
  282. {
  283. KSSTREAM_HEADER Header;
  284. OVERLAPPED Signal;
  285. } DATAPACKET;
  286. typedef struct __PaIOPacket
  287. {
  288. DATAPACKET* packet;
  289. unsigned startByte;
  290. unsigned lengthBytes;
  291. } PaIOPacket;
  292. typedef struct __PaWinWdmIOInfo
  293. {
  294. PaWinWdmPin* pPin;
  295. char* hostBuffer;
  296. unsigned hostBufferSize;
  297. unsigned framesPerBuffer;
  298. unsigned bytesPerFrame;
  299. unsigned bytesPerSample;
  300. unsigned noOfPackets; /* Only used in WaveCyclic */
  301. HANDLE *events; /* noOfPackets handles (WaveCyclic) 1 (WaveRT) */
  302. DATAPACKET *packets; /* noOfPackets packets (WaveCyclic) 2 (WaveRT) */
  303. /* WaveRT polled mode */
  304. unsigned lastPosition;
  305. unsigned pollCntr;
  306. } PaWinWdmIOInfo;
  307. /* PaWinWdmStream - a stream data structure specifically for this implementation */
  308. struct __PaWinWdmStream
  309. {
  310. PaUtilStreamRepresentation streamRepresentation;
  311. PaWDMKSSpecificStreamInfo hostApiStreamInfo; /* This holds info that is exposed through PaStreamInfo */
  312. PaUtilCpuLoadMeasurer cpuLoadMeasurer;
  313. PaUtilBufferProcessor bufferProcessor;
  314. #if PA_TRACE_REALTIME_EVENTS
  315. LogHandle hLog;
  316. #endif
  317. PaUtilAllocationGroup* allocGroup;
  318. PaWinWdmIOInfo capture;
  319. PaWinWdmIOInfo render;
  320. int streamStarted;
  321. int streamActive;
  322. int streamStop;
  323. int streamAbort;
  324. int oldProcessPriority;
  325. HANDLE streamThread;
  326. HANDLE eventAbort;
  327. HANDLE eventStreamStart[StreamStart_kCnt]; /* 0 = OK, 1 = Failed */
  328. PaError threadResult;
  329. PaStreamFlags streamFlags;
  330. /* Capture ring buffer */
  331. PaUtilRingBuffer ringBuffer;
  332. char* ringBufferData;
  333. /* These values handle the case where the user wants to use fewer
  334. * channels than the device has */
  335. int userInputChannels;
  336. int deviceInputChannels;
  337. int userOutputChannels;
  338. int deviceOutputChannels;
  339. };
  340. /* Gather all processing variables in a struct */
  341. struct __PaProcessThreadInfo
  342. {
  343. PaWinWdmStream *stream;
  344. PaStreamCallbackTimeInfo ti;
  345. PaStreamCallbackFlags underover;
  346. int cbResult;
  347. volatile int pending;
  348. volatile int priming;
  349. volatile int pinsStarted;
  350. unsigned long timeout;
  351. unsigned captureHead;
  352. unsigned captureTail;
  353. unsigned renderHead;
  354. unsigned renderTail;
  355. PaIOPacket capturePackets[4];
  356. PaIOPacket renderPackets[4];
  357. };
  358. /* Used for transferring device infos during scanning / rescanning */
  359. typedef struct __PaWinWDMScanDeviceInfosResults
  360. {
  361. PaDeviceInfo **deviceInfos;
  362. PaDeviceIndex defaultInputDevice;
  363. PaDeviceIndex defaultOutputDevice;
  364. } PaWinWDMScanDeviceInfosResults;
  365. static const unsigned cPacketsArrayMask = 3;
  366. HMODULE DllKsUser = NULL;
  367. KSCREATEPIN* FunctionKsCreatePin = NULL;
  368. /* prototypes for functions declared in this file */
  369. #ifdef __cplusplus
  370. extern "C"
  371. {
  372. #endif /* __cplusplus */
  373. PaError PaWinWdm_Initialize( PaUtilHostApiRepresentation **hostApi, PaHostApiIndex index );
  374. #ifdef __cplusplus
  375. }
  376. #endif /* __cplusplus */
  377. /* Low level I/O functions */
  378. static PaError WdmSyncIoctl(HANDLE handle,
  379. unsigned long ioctlNumber,
  380. void* inBuffer,
  381. unsigned long inBufferCount,
  382. void* outBuffer,
  383. unsigned long outBufferCount,
  384. unsigned long* bytesReturned);
  385. static PaError WdmGetPropertySimple(HANDLE handle,
  386. const GUID* const guidPropertySet,
  387. unsigned long property,
  388. void* value,
  389. unsigned long valueCount);
  390. static PaError WdmSetPropertySimple(HANDLE handle,
  391. const GUID* const guidPropertySet,
  392. unsigned long property,
  393. void* value,
  394. unsigned long valueCount,
  395. void* instance,
  396. unsigned long instanceCount);
  397. static PaError WdmGetPinPropertySimple(HANDLE handle,
  398. unsigned long pinId,
  399. const GUID* const guidPropertySet,
  400. unsigned long property,
  401. void* value,
  402. unsigned long valueCount,
  403. unsigned long* byteCount);
  404. static PaError WdmGetPinPropertyMulti(HANDLE handle,
  405. unsigned long pinId,
  406. const GUID* const guidPropertySet,
  407. unsigned long property,
  408. KSMULTIPLE_ITEM** ksMultipleItem);
  409. static PaError WdmGetPropertyMulti(HANDLE handle,
  410. const GUID* const guidPropertySet,
  411. unsigned long property,
  412. KSMULTIPLE_ITEM** ksMultipleItem);
  413. static PaError WdmSetMuxNodeProperty(HANDLE handle,
  414. ULONG nodeId,
  415. ULONG pinId);
  416. /** Pin management functions */
  417. static PaWinWdmPin* PinNew(PaWinWdmFilter* parentFilter, unsigned long pinId, PaError* error);
  418. static void PinFree(PaWinWdmPin* pin);
  419. static void PinClose(PaWinWdmPin* pin);
  420. static PaError PinInstantiate(PaWinWdmPin* pin);
  421. /*static PaError PinGetState(PaWinWdmPin* pin, KSSTATE* state); NOT USED */
  422. static PaError PinSetState(PaWinWdmPin* pin, KSSTATE state);
  423. static PaError PinSetFormat(PaWinWdmPin* pin, const WAVEFORMATEX* format);
  424. static PaError PinIsFormatSupported(PaWinWdmPin* pin, const WAVEFORMATEX* format);
  425. /* WaveRT support */
  426. static PaError PinQueryNotificationSupport(PaWinWdmPin* pPin, BOOL* pbResult);
  427. static PaError PinGetBuffer(PaWinWdmPin* pPin, void** pBuffer, DWORD* pRequestedBufSize, BOOL* pbCallMemBarrier);
  428. static PaError PinRegisterPositionRegister(PaWinWdmPin* pPin);
  429. static PaError PinRegisterNotificationHandle(PaWinWdmPin* pPin, HANDLE handle);
  430. static PaError PinUnregisterNotificationHandle(PaWinWdmPin* pPin, HANDLE handle);
  431. static PaError PinGetHwLatency(PaWinWdmPin* pPin, ULONG* pFifoSize, ULONG* pChipsetDelay, ULONG* pCodecDelay);
  432. static PaError PinGetAudioPositionDirect(PaWinWdmPin* pPin, ULONG* pPosition);
  433. static PaError PinGetAudioPositionViaIOCTL(PaWinWdmPin* pPin, ULONG* pPosition);
  434. /* Filter management functions */
  435. static PaWinWdmFilter* FilterNew(PaWDMKSType type, DWORD devNode, const wchar_t* filterName, const wchar_t* friendlyName, PaError* error);
  436. static PaError FilterInitializePins(PaWinWdmFilter* filter);
  437. static void FilterFree(PaWinWdmFilter* filter);
  438. static void FilterAddRef(PaWinWdmFilter* filter);
  439. static PaWinWdmPin* FilterCreatePin(
  440. PaWinWdmFilter* filter,
  441. int pinId,
  442. const WAVEFORMATEX* wfex,
  443. PaError* error);
  444. static PaError FilterUse(PaWinWdmFilter* filter);
  445. static void FilterRelease(PaWinWdmFilter* filter);
  446. /* Hot plug functions */
  447. static BOOL IsDeviceTheSame(const PaWinWdmDeviceInfo* pDev1,
  448. const PaWinWdmDeviceInfo* pDev2);
  449. /* Interface functions */
  450. static void Terminate( struct PaUtilHostApiRepresentation *hostApi );
  451. static PaError IsFormatSupported(
  452. struct PaUtilHostApiRepresentation *hostApi,
  453. const PaStreamParameters *inputParameters,
  454. const PaStreamParameters *outputParameters,
  455. double sampleRate );
  456. static PaError ScanDeviceInfos( struct PaUtilHostApiRepresentation *hostApi, PaHostApiIndex index, void **newDeviceInfos, int *newDeviceCount );
  457. static PaError CommitDeviceInfos( struct PaUtilHostApiRepresentation *hostApi, PaHostApiIndex index, void *deviceInfos, int deviceCount );
  458. static PaError DisposeDeviceInfos( struct PaUtilHostApiRepresentation *hostApi, void *deviceInfos, int deviceCount );
  459. static PaError OpenStream(
  460. struct PaUtilHostApiRepresentation *hostApi,
  461. PaStream** s,
  462. const PaStreamParameters *inputParameters,
  463. const PaStreamParameters *outputParameters,
  464. double sampleRate,
  465. unsigned long framesPerBuffer,
  466. PaStreamFlags streamFlags,
  467. PaStreamCallback *streamCallback,
  468. void *userData );
  469. static PaError CloseStream( PaStream* stream );
  470. static PaError StartStream( PaStream *stream );
  471. static PaError StopStream( PaStream *stream );
  472. static PaError AbortStream( PaStream *stream );
  473. static PaError IsStreamStopped( PaStream *s );
  474. static PaError IsStreamActive( PaStream *stream );
  475. static PaTime GetStreamTime( PaStream *stream );
  476. static double GetStreamCpuLoad( PaStream* stream );
  477. static PaError ReadStream(
  478. PaStream* stream,
  479. void *buffer,
  480. unsigned long frames );
  481. static PaError WriteStream(
  482. PaStream* stream,
  483. const void *buffer,
  484. unsigned long frames );
  485. static signed long GetStreamReadAvailable( PaStream* stream );
  486. static signed long GetStreamWriteAvailable( PaStream* stream );
  487. /* Utility functions */
  488. static unsigned long GetWfexSize(const WAVEFORMATEX* wfex);
  489. static PaWinWdmFilter** BuildFilterList(int* filterCount, int* noOfPaDevices, PaError* result);
  490. static BOOL PinWrite(HANDLE h, DATAPACKET* p);
  491. static BOOL PinRead(HANDLE h, DATAPACKET* p);
  492. static void DuplicateFirstChannelInt16(void* buffer, int channels, int samples);
  493. static void DuplicateFirstChannelInt24(void* buffer, int channels, int samples);
  494. PA_THREAD_FUNC ProcessingThread(void*);
  495. /* Pin handler functions */
  496. static PaError PaPinCaptureEventHandler_WaveCyclic(PaProcessThreadInfo* pInfo, unsigned eventIndex);
  497. static PaError PaPinCaptureSubmitHandler_WaveCyclic(PaProcessThreadInfo* pInfo, unsigned eventIndex);
  498. static PaError PaPinRenderEventHandler_WaveCyclic(PaProcessThreadInfo* pInfo, unsigned eventIndex);
  499. static PaError PaPinRenderSubmitHandler_WaveCyclic(PaProcessThreadInfo* pInfo, unsigned eventIndex);
  500. static PaError PaPinCaptureEventHandler_WaveRTEvent(PaProcessThreadInfo* pInfo, unsigned eventIndex);
  501. static PaError PaPinCaptureEventHandler_WaveRTPolled(PaProcessThreadInfo* pInfo, unsigned eventIndex);
  502. static PaError PaPinCaptureSubmitHandler_WaveRTEvent(PaProcessThreadInfo* pInfo, unsigned eventIndex);
  503. static PaError PaPinCaptureSubmitHandler_WaveRTPolled(PaProcessThreadInfo* pInfo, unsigned eventIndex);
  504. static PaError PaPinRenderEventHandler_WaveRTEvent(PaProcessThreadInfo* pInfo, unsigned eventIndex);
  505. static PaError PaPinRenderEventHandler_WaveRTPolled(PaProcessThreadInfo* pInfo, unsigned eventIndex);
  506. static PaError PaPinRenderSubmitHandler_WaveRTEvent(PaProcessThreadInfo* pInfo, unsigned eventIndex);
  507. static PaError PaPinRenderSubmitHandler_WaveRTPolled(PaProcessThreadInfo* pInfo, unsigned eventIndex);
  508. /* Function bodies */
  509. #if defined(_DEBUG) && defined(PA_ENABLE_DEBUG_OUTPUT)
  510. #define PA_WDMKS_SET_TREF
  511. static PaTime tRef = 0;
  512. static void PaWinWdmDebugPrintf(const char* fmt, ...)
  513. {
  514. va_list list;
  515. char buffer[1024];
  516. PaTime t = PaUtil_GetTime() - tRef;
  517. va_start(list, fmt);
  518. _vsnprintf(buffer, 1023, fmt, list);
  519. va_end(list);
  520. PaUtil_DebugPrint("%6.3lf: %s", t, buffer);
  521. }
  522. #ifdef PA_DEBUG
  523. #undef PA_DEBUG
  524. #define PA_DEBUG(x) PaWinWdmDebugPrintf x ;
  525. #endif
  526. #endif
  527. static BOOL IsDeviceTheSame(const PaWinWdmDeviceInfo* pDev1,
  528. const PaWinWdmDeviceInfo* pDev2)
  529. {
  530. if (pDev1 == NULL || pDev2 == NULL)
  531. return FALSE;
  532. if (pDev1 == pDev2)
  533. return TRUE;
  534. if (strcmp(pDev1->compositeName, pDev2->compositeName) == 0)
  535. return TRUE;
  536. return FALSE;
  537. }
  538. static BOOL IsEarlierThanVista()
  539. {
  540. OSVERSIONINFO osvi;
  541. osvi.dwOSVersionInfoSize = sizeof(osvi);
  542. if (GetVersionEx(&osvi) && osvi.dwMajorVersion<6)
  543. {
  544. return TRUE;
  545. }
  546. return FALSE;
  547. }
  548. static void MemoryBarrierDummy(void)
  549. {
  550. /* Do nothing */
  551. }
  552. static void MemoryBarrierRead(void)
  553. {
  554. PaUtil_ReadMemoryBarrier();
  555. }
  556. static void MemoryBarrierWrite(void)
  557. {
  558. PaUtil_WriteMemoryBarrier();
  559. }
  560. static unsigned long GetWfexSize(const WAVEFORMATEX* wfex)
  561. {
  562. if( wfex->wFormatTag == WAVE_FORMAT_PCM )
  563. {
  564. return sizeof( WAVEFORMATEX );
  565. }
  566. else
  567. {
  568. return (sizeof( WAVEFORMATEX ) + wfex->cbSize);
  569. }
  570. }
  571. static void PaWinWDM_SetLastErrorInfo(long errCode, const char* fmt, ...)
  572. {
  573. va_list list;
  574. char buffer[1024];
  575. va_start(list, fmt);
  576. _vsnprintf(buffer, 1023, fmt, list);
  577. va_end(list);
  578. PaUtil_SetLastHostErrorInfo(paWDMKS, errCode, buffer);
  579. }
  580. /*
  581. Low level pin/filter access functions
  582. */
  583. static PaError WdmSyncIoctl(
  584. HANDLE handle,
  585. unsigned long ioctlNumber,
  586. void* inBuffer,
  587. unsigned long inBufferCount,
  588. void* outBuffer,
  589. unsigned long outBufferCount,
  590. unsigned long* bytesReturned)
  591. {
  592. PaError result = paNoError;
  593. unsigned long dummyBytesReturned = 0;
  594. BOOL bRes;
  595. if( !bytesReturned )
  596. {
  597. /* Use a dummy as the caller hasn't supplied one */
  598. bytesReturned = &dummyBytesReturned;
  599. }
  600. bRes = DeviceIoControl(handle, ioctlNumber, inBuffer, inBufferCount, outBuffer, outBufferCount, bytesReturned, NULL);
  601. if (!bRes)
  602. {
  603. unsigned long error = GetLastError();
  604. if ( !(((error == ERROR_INSUFFICIENT_BUFFER ) || ( error == ERROR_MORE_DATA )) &&
  605. ( ioctlNumber == IOCTL_KS_PROPERTY ) &&
  606. ( outBufferCount == 0 ) ) )
  607. {
  608. KSPROPERTY* ksProperty = (KSPROPERTY*)inBuffer;
  609. PaWinWDM_SetLastErrorInfo(result, "WdmSyncIoctl: DeviceIoControl GLE = 0x%08X (prop_set = {%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}, prop_id = %u)",
  610. error,
  611. ksProperty->Set.Data1, ksProperty->Set.Data2, ksProperty->Set.Data3,
  612. ksProperty->Set.Data4[0], ksProperty->Set.Data4[1],
  613. ksProperty->Set.Data4[2], ksProperty->Set.Data4[3],
  614. ksProperty->Set.Data4[4], ksProperty->Set.Data4[5],
  615. ksProperty->Set.Data4[6], ksProperty->Set.Data4[7],
  616. ksProperty->Id
  617. );
  618. result = paUnanticipatedHostError;
  619. }
  620. }
  621. return result;
  622. }
  623. static PaError WdmGetPropertySimple(HANDLE handle,
  624. const GUID* const guidPropertySet,
  625. unsigned long property,
  626. void* value,
  627. unsigned long valueCount)
  628. {
  629. PaError result;
  630. KSPROPERTY ksProperty;
  631. ksProperty.Set = *guidPropertySet;
  632. ksProperty.Id = property;
  633. ksProperty.Flags = KSPROPERTY_TYPE_GET;
  634. result = WdmSyncIoctl(
  635. handle,
  636. IOCTL_KS_PROPERTY,
  637. &ksProperty,
  638. sizeof(KSPROPERTY),
  639. value,
  640. valueCount,
  641. NULL);
  642. return result;
  643. }
  644. static PaError WdmSetPropertySimple(
  645. HANDLE handle,
  646. const GUID* const guidPropertySet,
  647. unsigned long property,
  648. void* value,
  649. unsigned long valueCount,
  650. void* instance,
  651. unsigned long instanceCount)
  652. {
  653. PaError result;
  654. KSPROPERTY* ksProperty;
  655. unsigned long propertyCount = 0;
  656. propertyCount = sizeof(KSPROPERTY) + instanceCount;
  657. ksProperty = (KSPROPERTY*)_alloca( propertyCount );
  658. if( !ksProperty )
  659. {
  660. return paInsufficientMemory;
  661. }
  662. ksProperty->Set = *guidPropertySet;
  663. ksProperty->Id = property;
  664. ksProperty->Flags = KSPROPERTY_TYPE_SET;
  665. if( instance )
  666. {
  667. memcpy((void*)((char*)ksProperty + sizeof(KSPROPERTY)), instance, instanceCount);
  668. }
  669. result = WdmSyncIoctl(
  670. handle,
  671. IOCTL_KS_PROPERTY,
  672. ksProperty,
  673. propertyCount,
  674. value,
  675. valueCount,
  676. NULL);
  677. return result;
  678. }
  679. static PaError WdmGetPinPropertySimple(
  680. HANDLE handle,
  681. unsigned long pinId,
  682. const GUID* const guidPropertySet,
  683. unsigned long property,
  684. void* value,
  685. unsigned long valueCount,
  686. unsigned long *byteCount)
  687. {
  688. PaError result;
  689. KSP_PIN ksPProp;
  690. ksPProp.Property.Set = *guidPropertySet;
  691. ksPProp.Property.Id = property;
  692. ksPProp.Property.Flags = KSPROPERTY_TYPE_GET;
  693. ksPProp.PinId = pinId;
  694. ksPProp.Reserved = 0;
  695. result = WdmSyncIoctl(
  696. handle,
  697. IOCTL_KS_PROPERTY,
  698. &ksPProp,
  699. sizeof(KSP_PIN),
  700. value,
  701. valueCount,
  702. byteCount);
  703. return result;
  704. }
  705. static PaError WdmGetPinPropertyMulti(
  706. HANDLE handle,
  707. unsigned long pinId,
  708. const GUID* const guidPropertySet,
  709. unsigned long property,
  710. KSMULTIPLE_ITEM** ksMultipleItem)
  711. {
  712. PaError result;
  713. unsigned long multipleItemSize = 0;
  714. KSP_PIN ksPProp;
  715. ksPProp.Property.Set = *guidPropertySet;
  716. ksPProp.Property.Id = property;
  717. ksPProp.Property.Flags = KSPROPERTY_TYPE_GET;
  718. ksPProp.PinId = pinId;
  719. ksPProp.Reserved = 0;
  720. result = WdmSyncIoctl(
  721. handle,
  722. IOCTL_KS_PROPERTY,
  723. &ksPProp.Property,
  724. sizeof(KSP_PIN),
  725. NULL,
  726. 0,
  727. &multipleItemSize);
  728. if( result != paNoError )
  729. {
  730. return result;
  731. }
  732. *ksMultipleItem = (KSMULTIPLE_ITEM*)PaUtil_AllocateMemory( multipleItemSize );
  733. if( !*ksMultipleItem )
  734. {
  735. return paInsufficientMemory;
  736. }
  737. result = WdmSyncIoctl(
  738. handle,
  739. IOCTL_KS_PROPERTY,
  740. &ksPProp,
  741. sizeof(KSP_PIN),
  742. (void*)*ksMultipleItem,
  743. multipleItemSize,
  744. NULL);
  745. if( result != paNoError )
  746. {
  747. PaUtil_FreeMemory( ksMultipleItem );
  748. }
  749. return result;
  750. }
  751. static PaError WdmGetPropertyMulti(HANDLE handle,
  752. const GUID* const guidPropertySet,
  753. unsigned long property,
  754. KSMULTIPLE_ITEM** ksMultipleItem)
  755. {
  756. PaError result;
  757. unsigned long multipleItemSize = 0;
  758. KSPROPERTY ksProp;
  759. ksProp.Set = *guidPropertySet;
  760. ksProp.Id = property;
  761. ksProp.Flags = KSPROPERTY_TYPE_GET;
  762. result = WdmSyncIoctl(
  763. handle,
  764. IOCTL_KS_PROPERTY,
  765. &ksProp,
  766. sizeof(KSPROPERTY),
  767. NULL,
  768. 0,
  769. &multipleItemSize);
  770. if( result != paNoError )
  771. {
  772. return result;
  773. }
  774. *ksMultipleItem = (KSMULTIPLE_ITEM*)PaUtil_AllocateMemory( multipleItemSize );
  775. if( !*ksMultipleItem )
  776. {
  777. return paInsufficientMemory;
  778. }
  779. result = WdmSyncIoctl(
  780. handle,
  781. IOCTL_KS_PROPERTY,
  782. &ksProp,
  783. sizeof(KSPROPERTY),
  784. (void*)*ksMultipleItem,
  785. multipleItemSize,
  786. NULL);
  787. if( result != paNoError )
  788. {
  789. PaUtil_FreeMemory( ksMultipleItem );
  790. }
  791. return result;
  792. }
  793. static PaError WdmSetMuxNodeProperty(HANDLE handle,
  794. ULONG nodeId,
  795. ULONG pinId)
  796. {
  797. PaError result = paNoError;
  798. KSNODEPROPERTY prop;
  799. prop.Property.Set = KSPROPSETID_Audio;
  800. prop.Property.Id = KSPROPERTY_AUDIO_MUX_SOURCE;
  801. prop.Property.Flags = KSPROPERTY_TYPE_SET | KSPROPERTY_TYPE_TOPOLOGY;
  802. prop.NodeId = nodeId;
  803. prop.Reserved = 0;
  804. result = WdmSyncIoctl(handle, IOCTL_KS_PROPERTY, &prop, sizeof(KSNODEPROPERTY), &pinId, sizeof(ULONG), NULL);
  805. return result;
  806. }
  807. /* Used when traversing topology for outputs */
  808. static const KSTOPOLOGY_CONNECTION* GetConnectionTo(const KSTOPOLOGY_CONNECTION* pFrom, PaWinWdmFilter* filter, int muxIdx)
  809. {
  810. unsigned i;
  811. const KSTOPOLOGY_CONNECTION* retval = NULL;
  812. const KSTOPOLOGY_CONNECTION* connections = (const KSTOPOLOGY_CONNECTION*)(filter->connections + 1);
  813. (void)muxIdx;
  814. PA_DEBUG(("GetConnectionTo: Checking %u connections... (pFrom = %p)", filter->connections->Count, pFrom));
  815. for (i = 0; i < filter->connections->Count; ++i)
  816. {
  817. const KSTOPOLOGY_CONNECTION* pConn = connections + i;
  818. if (pConn == pFrom)
  819. continue;
  820. if (pConn->FromNode == pFrom->ToNode)
  821. {
  822. retval = pConn;
  823. break;
  824. }
  825. }
  826. PA_DEBUG(("GetConnectionTo: Returning %p\n", retval));
  827. return retval;
  828. }
  829. /* Used when traversing topology for inputs */
  830. static const KSTOPOLOGY_CONNECTION* GetConnectionFrom(const KSTOPOLOGY_CONNECTION* pTo, PaWinWdmFilter* filter, int muxIdx)
  831. {
  832. unsigned i;
  833. const KSTOPOLOGY_CONNECTION* retval = NULL;
  834. const KSTOPOLOGY_CONNECTION* connections = (const KSTOPOLOGY_CONNECTION*)(filter->connections + 1);
  835. int muxCntr = 0;
  836. PA_DEBUG(("GetConnectionFrom: Checking %u connections... (pTo = %p)\n", filter->connections->Count, pTo));
  837. for (i = 0; i < filter->connections->Count; ++i)
  838. {
  839. const KSTOPOLOGY_CONNECTION* pConn = connections + i;
  840. if (pConn == pTo)
  841. continue;
  842. if (pConn->ToNode == pTo->FromNode)
  843. {
  844. if (muxIdx >= 0)
  845. {
  846. if (muxCntr < muxIdx)
  847. {
  848. ++muxCntr;
  849. continue;
  850. }
  851. }
  852. retval = pConn;
  853. break;
  854. }
  855. }
  856. PA_DEBUG(("GetConnectionFrom: Returning %p\n", retval));
  857. return retval;
  858. }
  859. static ULONG GetNumberOfConnectionsTo(const KSTOPOLOGY_CONNECTION* pTo, PaWinWdmFilter* filter)
  860. {
  861. ULONG retval = 0;
  862. unsigned i;
  863. const KSTOPOLOGY_CONNECTION* connections = (const KSTOPOLOGY_CONNECTION*)(filter->connections + 1);
  864. PA_DEBUG(("GetNumberOfConnectionsTo: Checking %u connections...", filter->connections->Count));
  865. for (i = 0; i < filter->connections->Count; ++i)
  866. {
  867. const KSTOPOLOGY_CONNECTION* pConn = connections + i;
  868. if (pConn->ToNode == pTo->FromNode &&
  869. (pTo->FromNode != KSFILTER_NODE || pConn->ToNodePin == pTo->FromNodePin))
  870. {
  871. ++retval;
  872. }
  873. }
  874. return retval;
  875. }
  876. typedef const KSTOPOLOGY_CONNECTION *(*TFnGetConnection)(const KSTOPOLOGY_CONNECTION*, PaWinWdmFilter*, int);
  877. static const KSTOPOLOGY_CONNECTION* FindStartConnectionFrom(ULONG startPin, PaWinWdmFilter* filter)
  878. {
  879. unsigned i;
  880. const KSTOPOLOGY_CONNECTION* connections = (const KSTOPOLOGY_CONNECTION*)(filter->connections + 1);
  881. PA_DEBUG(("FindStartConnectionFrom: Checking %u connections...", filter->connections->Count));
  882. for (i = 0; i < filter->connections->Count; ++i)
  883. {
  884. const KSTOPOLOGY_CONNECTION* pConn = connections + i;
  885. if (pConn->ToNode == KSFILTER_NODE && pConn->ToNodePin == startPin)
  886. {
  887. return pConn;
  888. }
  889. }
  890. assert(FALSE);
  891. return 0;
  892. }
  893. static const KSTOPOLOGY_CONNECTION* FindStartConnectionTo(ULONG startPin, PaWinWdmFilter* filter)
  894. {
  895. unsigned i;
  896. const KSTOPOLOGY_CONNECTION* connections = (const KSTOPOLOGY_CONNECTION*)(filter->connections + 1);
  897. PA_DEBUG(("FindStartConnectionTo: Checking %u connections...", filter->connections->Count));
  898. for (i = 0; i < filter->connections->Count; ++i)
  899. {
  900. const KSTOPOLOGY_CONNECTION* pConn = connections + i;
  901. if (pConn->FromNode == KSFILTER_NODE && pConn->FromNodePin == startPin)
  902. {
  903. return pConn;
  904. }
  905. }
  906. assert(FALSE);
  907. return 0;
  908. }
  909. static ULONG GetConnectedPin(ULONG startPin, BOOL forward, PaWinWdmFilter* filter, int muxPosition, ULONG *muxInputPinId, ULONG *muxNodeId)
  910. {
  911. const KSTOPOLOGY_CONNECTION *conn = NULL;
  912. TFnGetConnection fnGetConnection = forward ? GetConnectionTo : GetConnectionFrom ;
  913. while (1)
  914. {
  915. if (conn == NULL)
  916. {
  917. conn = forward ? FindStartConnectionTo(startPin, filter) : FindStartConnectionFrom(startPin, filter);
  918. }
  919. else
  920. {
  921. conn = fnGetConnection(conn, filter, -1);
  922. }
  923. /* Handling case of erroneous connection list */
  924. if (conn == NULL)
  925. {
  926. break;
  927. }
  928. if (forward ? conn->ToNode == KSFILTER_NODE : conn->FromNode == KSFILTER_NODE)
  929. {
  930. return forward ? conn->ToNodePin : conn->FromNodePin;
  931. }
  932. else
  933. {
  934. PA_DEBUG(("GetConnectedPin: count=%d, forward=%d, muxPosition=%d\n", filter->nodes->Count, forward, muxPosition));
  935. if (filter->nodes->Count > 0 && !forward && muxPosition >= 0)
  936. {
  937. const GUID* nodes = (const GUID*)(filter->nodes + 1);
  938. if (IsEqualGUID(&nodes[conn->FromNode], &KSNODETYPE_MUX))
  939. {
  940. ULONG nConn = GetNumberOfConnectionsTo(conn, filter);
  941. conn = fnGetConnection(conn, filter, muxPosition);
  942. if (conn == NULL)
  943. {
  944. break;
  945. }
  946. if (muxInputPinId != 0)
  947. {
  948. *muxInputPinId = conn->ToNodePin;
  949. }
  950. if (muxNodeId != 0)
  951. {
  952. *muxNodeId = conn->ToNode;
  953. }
  954. }
  955. }
  956. }
  957. }
  958. return KSFILTER_NODE;
  959. }
  960. static void DumpConnectionsAndNodes(PaWinWdmFilter* filter)
  961. {
  962. unsigned i;
  963. const KSTOPOLOGY_CONNECTION* connections = (const KSTOPOLOGY_CONNECTION*)(filter->connections + 1);
  964. const GUID* nodes = (const GUID*)(filter->nodes + 1);
  965. PA_DEBUG(("DumpConnectionsAndNodes: connections=%d, nodes=%d\n", filter->connections->Count, filter->nodes->Count));
  966. for (i=0; i < filter->connections->Count; ++i)
  967. {
  968. const KSTOPOLOGY_CONNECTION* pConn = connections + i;
  969. PA_DEBUG((" Connection: %u - FromNode=%u,FromPin=%u -> ToNode=%u,ToPin=%u\n",
  970. i,
  971. pConn->FromNode, pConn->FromNodePin,
  972. pConn->ToNode, pConn->ToNodePin
  973. ));
  974. }
  975. for (i=0; i < filter->nodes->Count; ++i)
  976. {
  977. const GUID* pConn = nodes + i;
  978. PA_DEBUG((" Node: %d - {%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}\n",
  979. i,
  980. pConn->Data1, pConn->Data2, pConn->Data3,
  981. pConn->Data4[0], pConn->Data4[1],
  982. pConn->Data4[2], pConn->Data4[3],
  983. pConn->Data4[4], pConn->Data4[5],
  984. pConn->Data4[6], pConn->Data4[7]
  985. ));
  986. }
  987. }
  988. typedef struct __PaUsbTerminalGUIDToName
  989. {
  990. USHORT usbGUID;
  991. wchar_t name[64];
  992. } PaUsbTerminalGUIDToName;
  993. static const PaUsbTerminalGUIDToName kNames[] =
  994. {
  995. /* Types copied from: http://msdn.microsoft.com/en-us/library/ff537742(v=vs.85).aspx */
  996. /* Input terminal types */
  997. { 0x0201, L"Microphone" },
  998. { 0x0202, L"Desktop Microphone" },
  999. { 0x0203, L"Personal Microphone" },
  1000. { 0x0204, L"Omni Directional Microphone" },
  1001. { 0x0205, L"Microphone Array" },
  1002. { 0x0206, L"Processing Microphone Array" },
  1003. /* Output terminal types */
  1004. { 0x0301, L"Speakers" },
  1005. { 0x0302, L"Headphones" },
  1006. { 0x0303, L"Head Mounted Display Audio" },
  1007. { 0x0304, L"Desktop Speaker" },
  1008. { 0x0305, L"Room Speaker" },
  1009. { 0x0306, L"Communication Speaker" },
  1010. { 0x0307, L"LFE Speakers" },
  1011. /* External terminal types */
  1012. { 0x0601, L"Analog" },
  1013. { 0x0602, L"Digital" },
  1014. { 0x0603, L"Line" },
  1015. { 0x0604, L"Audio" },
  1016. { 0x0605, L"SPDIF" },
  1017. };
  1018. static const unsigned kNamesCnt = sizeof(kNames)/sizeof(PaUsbTerminalGUIDToName);
  1019. static int PaUsbTerminalGUIDToNameCmp(const void* lhs, const void* rhs)
  1020. {
  1021. const PaUsbTerminalGUIDToName* pL = (const PaUsbTerminalGUIDToName*)lhs;
  1022. const PaUsbTerminalGUIDToName* pR = (const PaUsbTerminalGUIDToName*)rhs;
  1023. return ((int)(pL->usbGUID) - (int)(pR->usbGUID));
  1024. }
  1025. static PaError GetNameFromCategory(const GUID* pGUID, BOOL input, wchar_t* name, unsigned length)
  1026. {
  1027. PaError result = paUnanticipatedHostError;
  1028. USHORT usbTerminalGUID = (USHORT)(pGUID->Data1 - 0xDFF219E0);
  1029. if (input && usbTerminalGUID >= 0x301 && usbTerminalGUID < 0x400)
  1030. {
  1031. /* Output terminal name for an input !? Set it to Line! */
  1032. usbTerminalGUID = 0x603;
  1033. }
  1034. if (!input && usbTerminalGUID >= 0x201 && usbTerminalGUID < 0x300)
  1035. {
  1036. /* Input terminal name for an output !? Set it to Line! */
  1037. usbTerminalGUID = 0x603;
  1038. }
  1039. if (usbTerminalGUID >= 0x201 && usbTerminalGUID < 0x713)
  1040. {
  1041. PaUsbTerminalGUIDToName s = { usbTerminalGUID };
  1042. const PaUsbTerminalGUIDToName* ptr = bsearch(
  1043. &s,
  1044. kNames,
  1045. kNamesCnt,
  1046. sizeof(PaUsbTerminalGUIDToName),
  1047. PaUsbTerminalGUIDToNameCmp
  1048. );
  1049. if (ptr != 0)
  1050. {
  1051. PA_DEBUG(("GetNameFromCategory: USB GUID %04X -> '%S'\n", usbTerminalGUID, ptr->name));
  1052. if (name != NULL && length > 0)
  1053. {
  1054. int n = _snwprintf(name, length, L"%s", ptr->name);
  1055. if (usbTerminalGUID >= 0x601 && usbTerminalGUID < 0x700)
  1056. {
  1057. _snwprintf(name + n, length - n, L" %s", (input ? L"In":L"Out"));
  1058. }
  1059. }
  1060. result = paNoError;
  1061. }
  1062. }
  1063. else
  1064. {
  1065. PaWinWDM_SetLastErrorInfo(result, "GetNameFromCategory: usbTerminalGUID = %04X ", usbTerminalGUID);
  1066. }
  1067. return result;
  1068. }
  1069. static BOOL IsFrequencyWithinRange(const KSDATARANGE_AUDIO* range, int frequency)
  1070. {
  1071. if (frequency < (int)range->MinimumSampleFrequency)
  1072. return FALSE;
  1073. if (frequency > (int)range->MaximumSampleFrequency)
  1074. return FALSE;
  1075. return TRUE;
  1076. }
  1077. static BOOL IsBitsWithinRange(const KSDATARANGE_AUDIO* range, int noOfBits)
  1078. {
  1079. if (noOfBits < (int)range->MinimumBitsPerSample)
  1080. return FALSE;
  1081. if (noOfBits > (int)range->MaximumBitsPerSample)
  1082. return FALSE;
  1083. return TRUE;
  1084. }
  1085. /* Note: Somewhat different order compared to WMME implementation, as we want to focus on fidelity first */
  1086. static const int defaultSampleRateSearchOrder[] =
  1087. { 44100, 48000, 88200, 96000, 192000, 32000, 24000, 22050, 16000, 12000, 11025, 9600, 8000 };
  1088. static const int defaultSampleRateSearchOrderCount = sizeof(defaultSampleRateSearchOrder)/sizeof(defaultSampleRateSearchOrder[0]);
  1089. static int DefaultSampleFrequencyIndex(const KSDATARANGE_AUDIO* range)
  1090. {
  1091. int i;
  1092. for(i=0; i < defaultSampleRateSearchOrderCount; ++i)
  1093. {
  1094. int currentFrequency = defaultSampleRateSearchOrder[i];
  1095. if (IsFrequencyWithinRange(range, currentFrequency))
  1096. {
  1097. return i;
  1098. }
  1099. }
  1100. return -1;
  1101. }
  1102. /*
  1103. Create a new pin object belonging to a filter
  1104. The pin object holds all the configuration information about the pin
  1105. before it is opened, and then the handle of the pin after is opened
  1106. */
  1107. static PaWinWdmPin* PinNew(PaWinWdmFilter* parentFilter, unsigned long pinId, PaError* error)
  1108. {
  1109. PaWinWdmPin* pin;
  1110. PaError result;
  1111. unsigned long i;
  1112. KSMULTIPLE_ITEM* item = NULL;
  1113. KSIDENTIFIER* identifier;
  1114. KSDATARANGE* dataRange;
  1115. const ULONG streamingId = (parentFilter->devInfo.streamingType == Type_kWaveRT) ? KSINTERFACE_STANDARD_LOOPED_STREAMING : KSINTERFACE_STANDARD_STREAMING;
  1116. int defaultSampleRateIndex = defaultSampleRateSearchOrderCount;
  1117. PA_LOGE_;
  1118. PA_DEBUG(("PinNew: Creating pin %d:\n",pinId));
  1119. /* Allocate the new PIN object */
  1120. pin = (PaWinWdmPin*)PaUtil_AllocateMemory( sizeof(PaWinWdmPin) );
  1121. if( !pin )
  1122. {
  1123. result = paInsufficientMemory;
  1124. goto error;
  1125. }
  1126. /* Zero the pin object */
  1127. /* memset( (void*)pin, 0, sizeof(PaWinWdmPin) ); */
  1128. pin->parentFilter = parentFilter;
  1129. pin->pinId = pinId;
  1130. /* Allocate a connect structure */
  1131. pin->pinConnectSize = sizeof(KSPIN_CONNECT) + sizeof(KSDATAFORMAT_WAVEFORMATEX);
  1132. pin->pinConnect = (KSPIN_CONNECT*)PaUtil_AllocateMemory( pin->pinConnectSize );
  1133. if( !pin->pinConnect )
  1134. {
  1135. result = paInsufficientMemory;
  1136. goto error;
  1137. }
  1138. /* Configure the connect structure with default values */
  1139. pin->pinConnect->Interface.Set = KSINTERFACESETID_Standard;
  1140. pin->pinConnect->Interface.Id = streamingId;
  1141. pin->pinConnect->Interface.Flags = 0;
  1142. pin->pinConnect->Medium.Set = KSMEDIUMSETID_Standard;
  1143. pin->pinConnect->Medium.Id = KSMEDIUM_TYPE_ANYINSTANCE;
  1144. pin->pinConnect->Medium.Flags = 0;
  1145. pin->pinConnect->PinId = pinId;
  1146. pin->pinConnect->PinToHandle = NULL;
  1147. pin->pinConnect->Priority.PriorityClass = KSPRIORITY_NORMAL;
  1148. pin->pinConnect->Priority.PrioritySubClass = 1;
  1149. pin->ksDataFormatWfx = (KSDATAFORMAT_WAVEFORMATEX*)(pin->pinConnect + 1);
  1150. pin->ksDataFormatWfx->DataFormat.FormatSize = sizeof(KSDATAFORMAT_WAVEFORMATEX);
  1151. pin->ksDataFormatWfx->DataFormat.Flags = 0;
  1152. pin->ksDataFormatWfx->DataFormat.Reserved = 0;
  1153. pin->ksDataFormatWfx->DataFormat.MajorFormat = KSDATAFORMAT_TYPE_AUDIO;
  1154. pin->ksDataFormatWfx->DataFormat.SubFormat = KSDATAFORMAT_SUBTYPE_PCM;
  1155. pin->ksDataFormatWfx->DataFormat.Specifier = KSDATAFORMAT_SPECIFIER_WAVEFORMATEX;
  1156. pin->frameSize = 0; /* Unknown until we instantiate pin */
  1157. /* Get the COMMUNICATION property */
  1158. result = WdmGetPinPropertySimple(
  1159. parentFilter->handle,
  1160. pinId,
  1161. &KSPROPSETID_Pin,
  1162. KSPROPERTY_PIN_COMMUNICATION,
  1163. &pin->communication,
  1164. sizeof(KSPIN_COMMUNICATION),
  1165. NULL);
  1166. if( result != paNoError )
  1167. goto error;
  1168. if( /*(pin->communication != KSPIN_COMMUNICATION_SOURCE) &&*/
  1169. (pin->communication != KSPIN_COMMUNICATION_SINK) &&
  1170. (pin->communication != KSPIN_COMMUNICATION_BOTH) )
  1171. {
  1172. PA_DEBUG(("PinNew: Not source/sink\n"));
  1173. result = paInvalidDevice;
  1174. goto error;
  1175. }
  1176. /* Get dataflow information */
  1177. result = WdmGetPinPropertySimple(
  1178. parentFilter->handle,
  1179. pinId,
  1180. &KSPROPSETID_Pin,
  1181. KSPROPERTY_PIN_DATAFLOW,
  1182. &pin->dataFlow,
  1183. sizeof(KSPIN_DATAFLOW),
  1184. NULL);
  1185. if( result != paNoError )
  1186. goto error;
  1187. /* Get the INTERFACE property list */
  1188. result = WdmGetPinPropertyMulti(
  1189. parentFilter->handle,
  1190. pinId,
  1191. &KSPROPSETID_Pin,
  1192. KSPROPERTY_PIN_INTERFACES,
  1193. &item);
  1194. if( result != paNoError )
  1195. goto error;
  1196. identifier = (KSIDENTIFIER*)(item+1);
  1197. /* Check that at least one interface is STANDARD_STREAMING */
  1198. result = paUnanticipatedHostError;
  1199. for( i = 0; i < item->Count; i++ )
  1200. {
  1201. if( IsEqualGUID(&identifier[i].Set, &KSINTERFACESETID_Standard) && ( identifier[i].Id == streamingId ) )
  1202. {
  1203. result = paNoError;
  1204. break;
  1205. }
  1206. }
  1207. if( result != paNoError )
  1208. {
  1209. PA_DEBUG(("PinNew: No %s streaming\n", streamingId==KSINTERFACE_STANDARD_LOOPED_STREAMING?"looped":"standard"));
  1210. goto error;
  1211. }
  1212. /* Don't need interfaces any more */
  1213. PaUtil_FreeMemory( item );
  1214. item = NULL;
  1215. /* Get the MEDIUM properties list */
  1216. result = WdmGetPinPropertyMulti(
  1217. parentFilter->handle,
  1218. pinId,
  1219. &KSPROPSETID_Pin,
  1220. KSPROPERTY_PIN_MEDIUMS,
  1221. &item);
  1222. if( result != paNoError )
  1223. goto error;
  1224. identifier = (KSIDENTIFIER*)(item+1); /* Not actually necessary... */
  1225. /* Check that at least one medium is STANDARD_DEVIO */
  1226. result = paUnanticipatedHostError;
  1227. for( i = 0; i < item->Count; i++ )
  1228. {
  1229. if( IsEqualGUID(&identifier[i].Set, &KSMEDIUMSETID_Standard) && ( identifier[i].Id == KSMEDIUM_STANDARD_DEVIO ) )
  1230. {
  1231. result = paNoError;
  1232. break;
  1233. }
  1234. }
  1235. if( result != paNoError )
  1236. {
  1237. PA_DEBUG(("No standard devio\n"));
  1238. goto error;
  1239. }
  1240. /* Don't need mediums any more */
  1241. PaUtil_FreeMemory( item );
  1242. item = NULL;
  1243. /* Get DATARANGES */
  1244. result = WdmGetPinPropertyMulti(
  1245. parentFilter->handle,
  1246. pinId,
  1247. &KSPROPSETID_Pin,
  1248. KSPROPERTY_PIN_DATARANGES,
  1249. &pin->dataRangesItem);
  1250. if( result != paNoError )
  1251. goto error;
  1252. pin->dataRanges = (KSDATARANGE*)(pin->dataRangesItem +1);
  1253. /* Check that at least one datarange supports audio */
  1254. result = paUnanticipatedHostError;
  1255. dataRange = pin->dataRanges;
  1256. pin->maxChannels = 0;
  1257. pin->defaultSampleRate = 0;
  1258. pin->formats = 0;
  1259. PA_DEBUG(("PinNew: Checking %u no of dataranges...\n", pin->dataRangesItem->Count));
  1260. for( i = 0; i < pin->dataRangesItem->Count; i++)
  1261. {
  1262. PA_DEBUG(("PinNew: DR major format %x\n",*(unsigned long*)(&(dataRange->MajorFormat))));
  1263. /* Check that subformat is WAVEFORMATEX, PCM or WILDCARD */
  1264. if( IS_VALID_WAVEFORMATEX_GUID(&dataRange->SubFormat) ||
  1265. IsEqualGUID(&dataRange->SubFormat, &KSDATAFORMAT_SUBTYPE_PCM) ||
  1266. IsEqualGUID(&dataRange->SubFormat, &KSDATAFORMAT_SUBTYPE_IEEE_FLOAT) ||
  1267. IsEqualGUID(&dataRange->SubFormat, &KSDATAFORMAT_SUBTYPE_WILDCARD) ||
  1268. IsEqualGUID(&dataRange->MajorFormat, &KSDATAFORMAT_TYPE_AUDIO) )
  1269. {
  1270. int defaultIndex;
  1271. result = paNoError;
  1272. /* Record the maximum possible channels with this pin */
  1273. if( ((KSDATARANGE_AUDIO*)dataRange)->MaximumChannels == (ULONG) -1 )
  1274. {
  1275. pin->maxChannels = MAXIMUM_NUMBER_OF_CHANNELS;
  1276. }
  1277. else if( (int) ((KSDATARANGE_AUDIO*)dataRange)->MaximumChannels > pin->maxChannels )
  1278. {
  1279. pin->maxChannels = (int) ((KSDATARANGE_AUDIO*)dataRange)->MaximumChannels;
  1280. }
  1281. PA_DEBUG(("PinNew: MaxChannel: %d\n",pin->maxChannels));
  1282. /* Record the formats (bit depths) that are supported */
  1283. if( IsBitsWithinRange((KSDATARANGE_AUDIO*)dataRange, 8) )
  1284. {
  1285. pin->formats |= paInt8;
  1286. PA_DEBUG(("PinNew: Format PCM 8 bit supported\n"));
  1287. }
  1288. if( IsBitsWithinRange((KSDATARANGE_AUDIO*)dataRange, 16) )
  1289. {
  1290. pin->formats |= paInt16;
  1291. PA_DEBUG(("PinNew: Format PCM 16 bit supported\n"));
  1292. }
  1293. if( IsBitsWithinRange((KSDATARANGE_AUDIO*)dataRange, 24) )
  1294. {
  1295. pin->formats |= paInt24;
  1296. PA_DEBUG(("PinNew: Format PCM 24 bit supported\n"));
  1297. }
  1298. if( IsBitsWithinRange((KSDATARANGE_AUDIO*)dataRange, 32) )
  1299. {
  1300. if (IsEqualGUID(&dataRange->SubFormat, &KSDATAFORMAT_SUBTYPE_IEEE_FLOAT))
  1301. {
  1302. pin->formats |= paFloat32;
  1303. PA_DEBUG(("PinNew: Format IEEE float 32 bit supported\n"));
  1304. }
  1305. else
  1306. {
  1307. pin->formats |= paInt32;
  1308. PA_DEBUG(("PinNew: Format PCM 32 bit supported\n"));
  1309. }
  1310. }
  1311. defaultIndex = DefaultSampleFrequencyIndex((KSDATARANGE_AUDIO*)dataRange);
  1312. if (defaultIndex >= 0 && defaultIndex < defaultSampleRateIndex)
  1313. {
  1314. defaultSampleRateIndex = defaultIndex;
  1315. }
  1316. }
  1317. dataRange = (KSDATARANGE*)( ((char*)dataRange) + dataRange->FormatSize);
  1318. }
  1319. if( result != paNoError )
  1320. goto error;
  1321. /* If none of the frequencies searched for are present, there's something seriously wrong */
  1322. if (defaultSampleRateIndex == defaultSampleRateSearchOrderCount)
  1323. {
  1324. PA_DEBUG(("PinNew: No default sample rate found, skipping pin!\n"));
  1325. PaWinWDM_SetLastErrorInfo(paUnanticipatedHostError, "PinNew: No default sample rate found");
  1326. result = paUnanticipatedHostError;
  1327. goto error;
  1328. }
  1329. /* Set the default sample rate */
  1330. pin->defaultSampleRate = defaultSampleRateSearchOrder[defaultSampleRateIndex];
  1331. PA_DEBUG(("PinNew: Default sample rate = %d Hz\n", pin->defaultSampleRate));
  1332. /* Get instance information */
  1333. result = WdmGetPinPropertySimple(
  1334. parentFilter->handle,
  1335. pinId,
  1336. &KSPROPSETID_Pin,
  1337. KSPROPERTY_PIN_CINSTANCES,
  1338. &pin->instances,
  1339. sizeof(KSPIN_CINSTANCES),
  1340. NULL);
  1341. if( result != paNoError )
  1342. goto error;
  1343. /* If WaveRT, check if pin supports notification mode */
  1344. if (parentFilter->devInfo.streamingType == Type_kWaveRT)
  1345. {
  1346. BOOL bSupportsNotification = FALSE;
  1347. if (PinQueryNotificationSupport(pin, &bSupportsNotification) == paNoError)
  1348. {
  1349. pin->pinKsSubType = bSupportsNotification ? SubType_kNotification : SubType_kPolled;
  1350. }
  1351. }
  1352. /* Query pin name (which means we need to traverse to non IRP pin, via physical connection to topology filter pin, through
  1353. its nodes to the endpoint pin, and get that ones name... phew...) */
  1354. PA_DEBUG(("PinNew: Finding topology pin...\n"));
  1355. {
  1356. ULONG topoPinId = GetConnectedPin(pinId, (pin->dataFlow == KSPIN_DATAFLOW_IN), parentFilter, -1, NULL, NULL);
  1357. const wchar_t kInputName[] = L"Input";
  1358. const wchar_t kOutputName[] = L"Output";
  1359. if (topoPinId != KSFILTER_NODE)
  1360. {
  1361. /* Get physical connection for topo pin */
  1362. unsigned long cbBytes = 0;
  1363. PA_DEBUG(("PinNew: Getting physical connection...\n"));
  1364. result = WdmGetPinPropertySimple(parentFilter->handle,
  1365. topoPinId,
  1366. &KSPROPSETID_Pin,
  1367. KSPROPERTY_PIN_PHYSICALCONNECTION,
  1368. 0,
  1369. 0,
  1370. &cbBytes
  1371. );
  1372. if (result != paNoError)
  1373. {
  1374. /* No physical connection -> there is no topology filter! So we get the name of the pin! */
  1375. PA_DEBUG(("PinNew: No physical connection! Getting the pin name\n"));
  1376. result = WdmGetPinPropertySimple(parentFilter->handle,
  1377. topoPinId,
  1378. &KSPROPSETID_Pin,
  1379. KSPROPERTY_PIN_NAME,
  1380. pin->friendlyName,
  1381. MAX_PATH,
  1382. NULL);
  1383. if (result != paNoError)
  1384. {
  1385. GUID category = {0};
  1386. /* Get pin category information */
  1387. result = WdmGetPinPropertySimple(parentFilter->handle,
  1388. topoPinId,
  1389. &KSPROPSETID_Pin,
  1390. KSPROPERTY_PIN_CATEGORY,
  1391. &category,
  1392. sizeof(GUID),
  1393. NULL);
  1394. if (result == paNoError)
  1395. {
  1396. result = GetNameFromCategory(&category, (pin->dataFlow == KSPIN_DATAFLOW_OUT), pin->friendlyName, MAX_PATH);
  1397. }
  1398. }
  1399. /* Make sure pin gets a name here... */
  1400. if (wcslen(pin->friendlyName) == 0)
  1401. {
  1402. wcscpy(pin->friendlyName, (pin->dataFlow == KSPIN_DATAFLOW_IN) ? kOutputName : kInputName);
  1403. #ifdef UNICODE
  1404. PA_DEBUG(("PinNew: Setting pin friendly name to '%s'\n", pin->friendlyName));
  1405. #else
  1406. PA_DEBUG(("PinNew: Setting pin friendly name to '%S'\n", pin->friendlyName));
  1407. #endif
  1408. }
  1409. /* This is then == the endpoint pin */
  1410. pin->endpointPinId = (pin->dataFlow == KSPIN_DATAFLOW_IN) ? pinId : topoPinId;
  1411. }
  1412. else
  1413. {
  1414. KSPIN_PHYSICALCONNECTION* pc = (KSPIN_PHYSICALCONNECTION*)PaUtil_AllocateMemory(cbBytes + 2);
  1415. PA_DEBUG(("PinNew: Physical connection found!\n"));
  1416. if (pc == NULL)
  1417. {
  1418. result = paInsufficientMemory;
  1419. goto error;
  1420. }
  1421. result = WdmGetPinPropertySimple(parentFilter->handle,
  1422. topoPinId,
  1423. &KSPROPSETID_Pin,
  1424. KSPROPERTY_PIN_PHYSICALCONNECTION,
  1425. pc,
  1426. cbBytes,
  1427. NULL
  1428. );
  1429. if (result == paNoError)
  1430. {
  1431. wchar_t symbLinkName[MAX_PATH];
  1432. wcsncpy(symbLinkName, pc->SymbolicLinkName, MAX_PATH);
  1433. if (symbLinkName[1] == TEXT('?'))
  1434. {
  1435. symbLinkName[1] = TEXT('\\');
  1436. }
  1437. if (pin->parentFilter->topologyFilter == NULL)
  1438. {
  1439. PA_DEBUG(("PinNew: Creating topology filter '%S'\n", symbLinkName));
  1440. pin->parentFilter->topologyFilter = FilterNew(Type_kNotUsed, 0, symbLinkName, L"", &result);
  1441. if (pin->parentFilter->topologyFilter == NULL)
  1442. {
  1443. PA_DEBUG(("PinNew: Failed creating topology filter\n"));
  1444. result = paUnanticipatedHostError;
  1445. PaWinWDM_SetLastErrorInfo(result, "Failed to create topology filter '%S'", symbLinkName);
  1446. goto error;
  1447. }
  1448. /* Copy info so we have it in device info */
  1449. wcsncpy(pin->parentFilter->devInfo.topologyPath, symbLinkName, MAX_PATH);
  1450. }
  1451. else
  1452. {
  1453. /* Must be the same */
  1454. assert(wcscmp(symbLinkName, pin->parentFilter->topologyFilter->devInfo.filterPath) == 0);
  1455. }
  1456. PA_DEBUG(("PinNew: Opening topology filter..."));
  1457. result = FilterUse(pin->parentFilter->topologyFilter);
  1458. if (result == paNoError)
  1459. {
  1460. unsigned long endpointPinId;
  1461. if (pin->dataFlow == KSPIN_DATAFLOW_IN)
  1462. {
  1463. /* The "endpointPinId" is what WASAPI looks at for pin names */
  1464. GUID category = {0};
  1465. PA_DEBUG(("PinNew: Checking for output endpoint pin id...\n"));
  1466. endpointPinId = GetConnectedPin(pc->Pin, TRUE, pin->parentFilter->topologyFilter, -1, NULL, NULL);
  1467. if (endpointPinId == KSFILTER_NODE)
  1468. {
  1469. result = paUnanticipatedHostError;
  1470. PaWinWDM_SetLastErrorInfo(result, "Failed to get endpoint pin ID on topology filter!");
  1471. goto error;
  1472. }
  1473. PA_DEBUG(("PinNew: Found endpoint pin id %u\n", endpointPinId));
  1474. /* Get pin category information */
  1475. result = WdmGetPinPropertySimple(pin->parentFilter->topologyFilter->handle,
  1476. endpointPinId,
  1477. &KSPROPSETID_Pin,
  1478. KSPROPERTY_PIN_CATEGORY,
  1479. &category,
  1480. sizeof(GUID),
  1481. NULL);
  1482. if (result == paNoError)
  1483. {
  1484. #if !PA_WDMKS_USE_CATEGORY_FOR_PIN_NAMES
  1485. wchar_t pinName[MAX_PATH];
  1486. PA_DEBUG(("PinNew: Getting pin name property..."));
  1487. /* Ok, try pin name also, and favor that if available */
  1488. result = WdmGetPinPropertySimple(pin->parentFilter->topologyFilter->handle,
  1489. endpointPinId,
  1490. &KSPROPSETID_Pin,
  1491. KSPROPERTY_PIN_NAME,
  1492. pinName,
  1493. MAX_PATH,
  1494. NULL);
  1495. if (result == paNoError && wcslen(pinName)>0)
  1496. {
  1497. wcsncpy(pin->friendlyName, pinName, MAX_PATH);
  1498. }
  1499. else
  1500. #endif
  1501. {
  1502. result = GetNameFromCategory(&category, (pin->dataFlow == KSPIN_DATAFLOW_OUT), pin->friendlyName, MAX_PATH);
  1503. }
  1504. if (wcslen(pin->friendlyName) == 0)
  1505. {
  1506. wcscpy(pin->friendlyName, L"Output");
  1507. }
  1508. #ifdef UNICODE
  1509. PA_DEBUG(("PinNew: Pin name '%s'\n", pin->friendlyName));
  1510. #else
  1511. PA_DEBUG(("PinNew: Pin name '%S'\n", pin->friendlyName));
  1512. #endif
  1513. }
  1514. /* Set endpoint pin ID (this is the topology INPUT pin, since portmixer will always traverse the
  1515. filter in audio streaming direction, see http://msdn.microsoft.com/en-us/library/windows/hardware/ff536331(v=vs.85).aspx
  1516. for more information)
  1517. */
  1518. pin->endpointPinId = pc->Pin;
  1519. }
  1520. else
  1521. {
  1522. unsigned muxCount = 0;
  1523. int muxPos = 0;
  1524. /* Max 64 multiplexer inputs... sanity check :) */
  1525. for (i = 0; i < 64; ++i)
  1526. {
  1527. ULONG muxNodeIdTest = (unsigned)-1;
  1528. PA_DEBUG(("PinNew: Checking for input endpoint pin id (%d)...\n", i));
  1529. endpointPinId = GetConnectedPin(pc->Pin,
  1530. FALSE,
  1531. pin->parentFilter->topologyFilter,
  1532. (int)i,
  1533. NULL,
  1534. &muxNodeIdTest);
  1535. if (endpointPinId == KSFILTER_NODE)
  1536. {
  1537. /* We're done */
  1538. PA_DEBUG(("PinNew: Done with inputs.\n", endpointPinId));
  1539. break;
  1540. }
  1541. else
  1542. {
  1543. /* The "endpointPinId" is what WASAPI looks at for pin names */
  1544. GUID category = {0};
  1545. PA_DEBUG(("PinNew: Found endpoint pin id %u\n", endpointPinId));
  1546. /* Get pin category information */
  1547. result = WdmGetPinPropertySimple(pin->parentFilter->topologyFilter->handle,
  1548. endpointPinId,
  1549. &KSPROPSETID_Pin,
  1550. KSPROPERTY_PIN_CATEGORY,
  1551. &category,
  1552. sizeof(GUID),
  1553. NULL);
  1554. if (result == paNoError)
  1555. {
  1556. if (muxNodeIdTest == (unsigned)-1)
  1557. {
  1558. /* Ok, try pin name, and favor that if available */
  1559. result = WdmGetPinPropertySimple(pin->parentFilter->topologyFilter->handle,
  1560. endpointPinId,
  1561. &KSPROPSETID_Pin,
  1562. KSPROPERTY_PIN_NAME,
  1563. pin->friendlyName,
  1564. MAX_PATH,
  1565. NULL);
  1566. if (result != paNoError)
  1567. {
  1568. result = GetNameFromCategory(&category, TRUE, pin->friendlyName, MAX_PATH);
  1569. }
  1570. break;
  1571. }
  1572. else
  1573. {
  1574. result = GetNameFromCategory(&category, TRUE, NULL, 0);
  1575. if (result == paNoError)
  1576. {
  1577. ++muxCount;
  1578. }
  1579. }
  1580. }
  1581. else
  1582. {
  1583. PA_DEBUG(("PinNew: Failed to get pin category"));
  1584. }
  1585. }
  1586. }
  1587. if (muxCount == 0)
  1588. {
  1589. pin->endpointPinId = endpointPinId;
  1590. /* Make sure we get a name for the pin */
  1591. if (wcslen(pin->friendlyName) == 0)
  1592. {
  1593. wcscpy(pin->friendlyName, kInputName);
  1594. }
  1595. #ifdef UNICODE
  1596. PA_DEBUG(("PinNew: Input friendly name '%s'\n", pin->friendlyName));
  1597. #else
  1598. PA_DEBUG(("PinNew: Input friendly name '%S'\n", pin->friendlyName));
  1599. #endif
  1600. }
  1601. else // muxCount > 0
  1602. {
  1603. PA_DEBUG(("PinNew: Setting up %u inputs\n", muxCount));
  1604. /* Now we redo the operation once known how many multiplexer positions there are */
  1605. pin->inputs = (PaWinWdmMuxedInput**)PaUtil_AllocateMemory(muxCount * sizeof(PaWinWdmMuxedInput*));
  1606. if (pin->inputs == NULL)
  1607. {
  1608. FilterRelease(pin->parentFilter->topologyFilter);
  1609. result = paInsufficientMemory;
  1610. goto error;
  1611. }
  1612. pin->inputCount = muxCount;
  1613. for (i = 0; i < muxCount; ++muxPos)
  1614. {
  1615. PA_DEBUG(("PinNew: Setting up input %u...\n", i));
  1616. if (pin->inputs[i] == NULL)
  1617. {
  1618. pin->inputs[i] = (PaWinWdmMuxedInput*)PaUtil_AllocateMemory(sizeof(PaWinWdmMuxedInput));
  1619. if (pin->inputs[i] == NULL)
  1620. {
  1621. FilterRelease(pin->parentFilter->topologyFilter);
  1622. result = paInsufficientMemory;
  1623. goto error;
  1624. }
  1625. }
  1626. endpointPinId = GetConnectedPin(pc->Pin,
  1627. FALSE,
  1628. pin->parentFilter->topologyFilter,
  1629. muxPos,
  1630. &pin->inputs[i]->muxPinId,
  1631. &pin->inputs[i]->muxNodeId);
  1632. if (endpointPinId != KSFILTER_NODE)
  1633. {
  1634. /* The "endpointPinId" is what WASAPI looks at for pin names */
  1635. GUID category = {0};
  1636. /* Set input endpoint ID */
  1637. pin->inputs[i]->endpointPinId = endpointPinId;
  1638. /* Get pin category information */
  1639. result = WdmGetPinPropertySimple(pin->parentFilter->topologyFilter->handle,
  1640. endpointPinId,
  1641. &KSPROPSETID_Pin,
  1642. KSPROPERTY_PIN_CATEGORY,
  1643. &category,
  1644. sizeof(GUID),
  1645. NULL);
  1646. if (result == paNoError)
  1647. {
  1648. /* Try pin name first, and if that is not defined, use category instead */
  1649. result = WdmGetPinPropertySimple(pin->parentFilter->topologyFilter->handle,
  1650. endpointPinId,
  1651. &KSPROPSETID_Pin,
  1652. KSPROPERTY_PIN_NAME,
  1653. pin->inputs[i]->friendlyName,
  1654. MAX_PATH,
  1655. NULL);
  1656. if (result != paNoError)
  1657. {
  1658. result = GetNameFromCategory(&category, TRUE, pin->inputs[i]->friendlyName, MAX_PATH);
  1659. if (result != paNoError)
  1660. {
  1661. /* Only specify name, let name hash in ScanDeviceInfos fix postfix enumerators */
  1662. wcscpy(pin->inputs[i]->friendlyName, kInputName);
  1663. }
  1664. }
  1665. #ifdef UNICODE
  1666. PA_DEBUG(("PinNew: Input (%u) friendly name '%s'\n", i, pin->inputs[i]->friendlyName));
  1667. #else
  1668. PA_DEBUG(("PinNew: Input (%u) friendly name '%S'\n", i, pin->inputs[i]->friendlyName));
  1669. #endif
  1670. ++i;
  1671. }
  1672. }
  1673. else
  1674. {
  1675. /* Should never come here! */
  1676. assert(FALSE);
  1677. }
  1678. }
  1679. }
  1680. }
  1681. }
  1682. }
  1683. PaUtil_FreeMemory(pc);
  1684. }
  1685. }
  1686. else
  1687. {
  1688. PA_DEBUG(("PinNew: No topology pin id found. Bad...\n"));
  1689. /* No TOPO pin id ??? This is bad. Ok, so we just say it is an input or output... */
  1690. wcscpy(pin->friendlyName, (pin->dataFlow == KSPIN_DATAFLOW_IN) ? kOutputName : kInputName);
  1691. }
  1692. }
  1693. /* Release topology filter if it has been used */
  1694. if (pin->parentFilter->topologyFilter && pin->parentFilter->topologyFilter->handle != NULL)
  1695. {
  1696. PA_DEBUG(("PinNew: Releasing topology filter...\n"));
  1697. FilterRelease(pin->parentFilter->topologyFilter);
  1698. }
  1699. /* Success */
  1700. *error = paNoError;
  1701. PA_DEBUG(("Pin created successfully\n"));
  1702. PA_LOGL_;
  1703. return pin;
  1704. error:
  1705. PA_DEBUG(("PinNew: Error %d\n", result));
  1706. /*
  1707. Error cleanup
  1708. */
  1709. PaUtil_FreeMemory( item );
  1710. if( pin )
  1711. {
  1712. if (pin->parentFilter->topologyFilter && pin->parentFilter->topologyFilter->handle != NULL)
  1713. {
  1714. FilterRelease(pin->parentFilter->topologyFilter);
  1715. }
  1716. PaUtil_FreeMemory( pin->pinConnect );
  1717. PaUtil_FreeMemory( pin->dataRangesItem );
  1718. PaUtil_FreeMemory( pin );
  1719. }
  1720. *error = result;
  1721. PA_LOGL_;
  1722. return NULL;
  1723. }
  1724. /*
  1725. Safely free all resources associated with the pin
  1726. */
  1727. static void PinFree(PaWinWdmPin* pin)
  1728. {
  1729. unsigned i;
  1730. PA_LOGE_;
  1731. if( pin )
  1732. {
  1733. PinClose(pin);
  1734. if( pin->pinConnect )
  1735. {
  1736. PaUtil_FreeMemory( pin->pinConnect );
  1737. }
  1738. if( pin->dataRangesItem )
  1739. {
  1740. PaUtil_FreeMemory( pin->dataRangesItem );
  1741. }
  1742. if( pin->inputs )
  1743. {
  1744. for (i = 0; i < pin->inputCount; ++i)
  1745. {
  1746. PaUtil_FreeMemory( pin->inputs[i] );
  1747. }
  1748. PaUtil_FreeMemory( pin->inputs );
  1749. }
  1750. PaUtil_FreeMemory( pin );
  1751. }
  1752. PA_LOGL_;
  1753. }
  1754. /*
  1755. If the pin handle is open, close it
  1756. */
  1757. static void PinClose(PaWinWdmPin* pin)
  1758. {
  1759. PA_LOGE_;
  1760. if( pin == NULL )
  1761. {
  1762. PA_DEBUG(("Closing NULL pin!"));
  1763. PA_LOGL_;
  1764. return;
  1765. }
  1766. if( pin->handle != NULL )
  1767. {
  1768. PinSetState( pin, KSSTATE_PAUSE );
  1769. PinSetState( pin, KSSTATE_STOP );
  1770. CloseHandle( pin->handle );
  1771. pin->handle = NULL;
  1772. FilterRelease(pin->parentFilter);
  1773. }
  1774. PA_LOGL_;
  1775. }
  1776. /*
  1777. Set the state of this (instantiated) pin
  1778. */
  1779. static PaError PinSetState(PaWinWdmPin* pin, KSSTATE state)
  1780. {
  1781. PaError result = paNoError;
  1782. KSPROPERTY prop;
  1783. PA_LOGE_;
  1784. prop.Set = KSPROPSETID_Connection;
  1785. prop.Id = KSPROPERTY_CONNECTION_STATE;
  1786. prop.Flags = KSPROPERTY_TYPE_SET;
  1787. if( pin == NULL )
  1788. return paInternalError;
  1789. if( pin->handle == NULL )
  1790. return paInternalError;
  1791. result = WdmSyncIoctl(pin->handle, IOCTL_KS_PROPERTY, &prop, sizeof(KSPROPERTY), &state, sizeof(KSSTATE), NULL);
  1792. PA_LOGL_;
  1793. return result;
  1794. }
  1795. static PaError PinInstantiate(PaWinWdmPin* pin)
  1796. {
  1797. PaError result;
  1798. unsigned long createResult;
  1799. KSALLOCATOR_FRAMING ksaf;
  1800. KSALLOCATOR_FRAMING_EX ksafex;
  1801. PA_LOGE_;
  1802. if( pin == NULL )
  1803. return paInternalError;
  1804. if(!pin->pinConnect)
  1805. return paInternalError;
  1806. FilterUse(pin->parentFilter);
  1807. createResult = FunctionKsCreatePin(
  1808. pin->parentFilter->handle,
  1809. pin->pinConnect,
  1810. GENERIC_WRITE | GENERIC_READ,
  1811. &pin->handle
  1812. );
  1813. PA_DEBUG(("Pin create result = 0x%08x\n",createResult));
  1814. if( createResult != ERROR_SUCCESS )
  1815. {
  1816. FilterRelease(pin->parentFilter);
  1817. pin->handle = NULL;
  1818. switch (createResult)
  1819. {
  1820. case ERROR_INVALID_PARAMETER:
  1821. /* First case when pin actually don't support the format */
  1822. return paSampleFormatNotSupported;
  1823. case ERROR_BAD_COMMAND:
  1824. /* Case when pin is occupied (by another application) */
  1825. return paDeviceUnavailable;
  1826. default:
  1827. /* All other cases */
  1828. return paInvalidDevice;
  1829. }
  1830. }
  1831. if (pin->parentFilter->devInfo.streamingType == Type_kWaveCyclic)
  1832. {
  1833. /* Framing size query only valid for WaveCyclic devices */
  1834. result = WdmGetPropertySimple(
  1835. pin->handle,
  1836. &KSPROPSETID_Connection,
  1837. KSPROPERTY_CONNECTION_ALLOCATORFRAMING,
  1838. &ksaf,
  1839. sizeof(ksaf));
  1840. if( result != paNoError )
  1841. {
  1842. result = WdmGetPropertySimple(
  1843. pin->handle,
  1844. &KSPROPSETID_Connection,
  1845. KSPROPERTY_CONNECTION_ALLOCATORFRAMING_EX,
  1846. &ksafex,
  1847. sizeof(ksafex));
  1848. if( result == paNoError )
  1849. {
  1850. pin->frameSize = ksafex.FramingItem[0].FramingRange.Range.MinFrameSize;
  1851. }
  1852. }
  1853. else
  1854. {
  1855. pin->frameSize = ksaf.FrameSize;
  1856. }
  1857. }
  1858. PA_LOGL_;
  1859. return paNoError;
  1860. }
  1861. static PaError PinSetFormat(PaWinWdmPin* pin, const WAVEFORMATEX* format)
  1862. {
  1863. unsigned long size;
  1864. void* newConnect;
  1865. PA_LOGE_;
  1866. if( pin == NULL )
  1867. return paInternalError;
  1868. if( format == NULL )
  1869. return paInternalError;
  1870. size = GetWfexSize(format) + sizeof(KSPIN_CONNECT) + sizeof(KSDATAFORMAT_WAVEFORMATEX) - sizeof(WAVEFORMATEX);
  1871. if( pin->pinConnectSize != size )
  1872. {
  1873. newConnect = PaUtil_AllocateMemory( size );
  1874. if( newConnect == NULL )
  1875. return paInsufficientMemory;
  1876. memcpy( newConnect, (void*)pin->pinConnect, min(pin->pinConnectSize,size) );
  1877. PaUtil_FreeMemory( pin->pinConnect );
  1878. pin->pinConnect = (KSPIN_CONNECT*)newConnect;
  1879. pin->pinConnectSize = size;
  1880. pin->ksDataFormatWfx = (KSDATAFORMAT_WAVEFORMATEX*)((KSPIN_CONNECT*)newConnect + 1);
  1881. pin->ksDataFormatWfx->DataFormat.FormatSize = size - sizeof(KSPIN_CONNECT);
  1882. }
  1883. memcpy( (void*)&(pin->ksDataFormatWfx->WaveFormatEx), format, GetWfexSize(format) );
  1884. pin->ksDataFormatWfx->DataFormat.SampleSize = (unsigned short)(format->nChannels * (format->wBitsPerSample / 8));
  1885. PA_LOGL_;
  1886. return paNoError;
  1887. }
  1888. static PaError PinIsFormatSupported(PaWinWdmPin* pin, const WAVEFORMATEX* format)
  1889. {
  1890. KSDATARANGE_AUDIO* dataRange;
  1891. unsigned long count;
  1892. GUID guid = DYNAMIC_GUID( DEFINE_WAVEFORMATEX_GUID(format->wFormatTag) );
  1893. PaError result = paInvalidDevice;
  1894. const WAVEFORMATEXTENSIBLE* pFormatExt = (format->wFormatTag == WAVE_FORMAT_EXTENSIBLE) ? (const WAVEFORMATEXTENSIBLE*)format : 0;
  1895. PA_LOGE_;
  1896. if( pFormatExt != 0 )
  1897. {
  1898. guid = pFormatExt->SubFormat;
  1899. }
  1900. dataRange = (KSDATARANGE_AUDIO*)pin->dataRanges;
  1901. for(count = 0;
  1902. count<pin->dataRangesItem->Count;
  1903. count++,
  1904. dataRange = (KSDATARANGE_AUDIO*)( ((char*)dataRange) + dataRange->DataRange.FormatSize)) /* Need to update dataRange here, due to 'continue' !! */
  1905. {
  1906. /* Check major format*/
  1907. if (!(IsEqualGUID(&(dataRange->DataRange.MajorFormat), &KSDATAFORMAT_TYPE_AUDIO) ||
  1908. IsEqualGUID(&(dataRange->DataRange.MajorFormat), &KSDATAFORMAT_TYPE_WILDCARD)))
  1909. {
  1910. continue;
  1911. }
  1912. /* This is an audio or wildcard datarange... */
  1913. if (! (IsEqualGUID(&(dataRange->DataRange.SubFormat), &KSDATAFORMAT_SUBTYPE_WILDCARD) ||
  1914. IsEqualGUID(&(dataRange->DataRange.SubFormat), &KSDATAFORMAT_SUBTYPE_PCM) ||
  1915. IsEqualGUID(&(dataRange->DataRange.SubFormat), &guid) ))
  1916. {
  1917. continue;
  1918. }
  1919. /* Check specifier... */
  1920. if (! (IsEqualGUID(&(dataRange->DataRange.Specifier), &KSDATAFORMAT_SPECIFIER_WILDCARD) ||
  1921. IsEqualGUID(&(dataRange->DataRange.Specifier), &KSDATAFORMAT_SPECIFIER_WAVEFORMATEX)) )
  1922. {
  1923. continue;
  1924. }
  1925. PA_DEBUG(("Pin:%x, DataRange:%d\n",(void*)pin,count));
  1926. PA_DEBUG(("\tFormatSize:%d, SampleSize:%d\n",dataRange->DataRange.FormatSize,dataRange->DataRange.SampleSize));
  1927. PA_DEBUG(("\tMaxChannels:%d\n",dataRange->MaximumChannels));
  1928. PA_DEBUG(("\tBits:%d-%d\n",dataRange->MinimumBitsPerSample,dataRange->MaximumBitsPerSample));
  1929. PA_DEBUG(("\tSampleRate:%d-%d\n",dataRange->MinimumSampleFrequency,dataRange->MaximumSampleFrequency));
  1930. if( dataRange->MaximumChannels != (ULONG)-1 &&
  1931. dataRange->MaximumChannels < format->nChannels )
  1932. {
  1933. result = paInvalidChannelCount;
  1934. continue;
  1935. }
  1936. if (pFormatExt != 0)
  1937. {
  1938. if ( dataRange->MinimumBitsPerSample > pFormatExt->Samples.wValidBitsPerSample )
  1939. {
  1940. result = paSampleFormatNotSupported;
  1941. continue;
  1942. }
  1943. if ( dataRange->MaximumBitsPerSample < pFormatExt->Samples.wValidBitsPerSample )
  1944. {
  1945. result = paSampleFormatNotSupported;
  1946. continue;
  1947. }
  1948. }
  1949. else
  1950. {
  1951. if( dataRange->MinimumBitsPerSample > format->wBitsPerSample )
  1952. {
  1953. result = paSampleFormatNotSupported;
  1954. continue;
  1955. }
  1956. if( dataRange->MaximumBitsPerSample < format->wBitsPerSample )
  1957. {
  1958. result = paSampleFormatNotSupported;
  1959. continue;
  1960. }
  1961. }
  1962. if( dataRange->MinimumSampleFrequency > format->nSamplesPerSec )
  1963. {
  1964. result = paInvalidSampleRate;
  1965. continue;
  1966. }
  1967. if( dataRange->MaximumSampleFrequency < format->nSamplesPerSec )
  1968. {
  1969. result = paInvalidSampleRate;
  1970. continue;
  1971. }
  1972. /* Success! */
  1973. result = paNoError;
  1974. break;
  1975. }
  1976. PA_LOGL_;
  1977. return result;
  1978. }
  1979. static PaError PinQueryNotificationSupport(PaWinWdmPin* pPin, BOOL* pbResult)
  1980. {
  1981. PaError result = paNoError;
  1982. KSPROPERTY propIn;
  1983. propIn.Set = KSPROPSETID_RtAudio;
  1984. propIn.Id = 8; /* = KSPROPERTY_RTAUDIO_QUERY_NOTIFICATION_SUPPORT */
  1985. propIn.Flags = KSPROPERTY_TYPE_GET;
  1986. result = WdmSyncIoctl(pPin->handle, IOCTL_KS_PROPERTY,
  1987. &propIn,
  1988. sizeof(KSPROPERTY),
  1989. pbResult,
  1990. sizeof(BOOL),
  1991. NULL);
  1992. if (result != paNoError)
  1993. {
  1994. PA_DEBUG(("Failed PinQueryNotificationSupport\n"));
  1995. }
  1996. return result;
  1997. }
  1998. static PaError PinGetBufferWithNotification(PaWinWdmPin* pPin, void** pBuffer, DWORD* pRequestedBufSize, BOOL* pbCallMemBarrier)
  1999. {
  2000. PaError result = paNoError;
  2001. KSRTAUDIO_BUFFER_PROPERTY_WITH_NOTIFICATION propIn;
  2002. KSRTAUDIO_BUFFER propOut;
  2003. propIn.BaseAddress = 0;
  2004. propIn.NotificationCount = 2;
  2005. propIn.RequestedBufferSize = *pRequestedBufSize;
  2006. propIn.Property.Set = KSPROPSETID_RtAudio;
  2007. propIn.Property.Id = KSPROPERTY_RTAUDIO_BUFFER_WITH_NOTIFICATION;
  2008. propIn.Property.Flags = KSPROPERTY_TYPE_GET;
  2009. result = WdmSyncIoctl(pPin->handle, IOCTL_KS_PROPERTY,
  2010. &propIn,
  2011. sizeof(KSRTAUDIO_BUFFER_PROPERTY_WITH_NOTIFICATION),
  2012. &propOut,
  2013. sizeof(KSRTAUDIO_BUFFER),
  2014. NULL);
  2015. if (result == paNoError)
  2016. {
  2017. *pBuffer = propOut.BufferAddress;
  2018. *pRequestedBufSize = propOut.ActualBufferSize;
  2019. *pbCallMemBarrier = propOut.CallMemoryBarrier;
  2020. }
  2021. else
  2022. {
  2023. PA_DEBUG(("Failed to get buffer with notification\n"));
  2024. }
  2025. return result;
  2026. }
  2027. static PaError PinGetBufferWithoutNotification(PaWinWdmPin* pPin, void** pBuffer, DWORD* pRequestedBufSize, BOOL* pbCallMemBarrier)
  2028. {
  2029. PaError result = paNoError;
  2030. KSRTAUDIO_BUFFER_PROPERTY propIn;
  2031. KSRTAUDIO_BUFFER propOut;
  2032. propIn.BaseAddress = NULL;
  2033. propIn.RequestedBufferSize = *pRequestedBufSize;
  2034. propIn.Property.Set = KSPROPSETID_RtAudio;
  2035. propIn.Property.Id = KSPROPERTY_RTAUDIO_BUFFER;
  2036. propIn.Property.Flags = KSPROPERTY_TYPE_GET;
  2037. result = WdmSyncIoctl(pPin->handle, IOCTL_KS_PROPERTY,
  2038. &propIn,
  2039. sizeof(KSRTAUDIO_BUFFER_PROPERTY),
  2040. &propOut,
  2041. sizeof(KSRTAUDIO_BUFFER),
  2042. NULL);
  2043. if (result == paNoError)
  2044. {
  2045. *pBuffer = propOut.BufferAddress;
  2046. *pRequestedBufSize = propOut.ActualBufferSize;
  2047. *pbCallMemBarrier = propOut.CallMemoryBarrier;
  2048. }
  2049. else
  2050. {
  2051. PA_DEBUG(("Failed to get buffer without notification\n"));
  2052. }
  2053. return result;
  2054. }
  2055. /* greatest common divisor - PGCD in French */
  2056. static unsigned long PaWinWDMGCD( unsigned long a, unsigned long b )
  2057. {
  2058. return (b==0) ? a : PaWinWDMGCD( b, a%b);
  2059. }
  2060. /* This function will handle getting the cyclic buffer from a WaveRT driver. Certain WaveRT drivers needs to have
  2061. requested buffer size on multiples of 128 bytes:
  2062. */
  2063. static PaError PinGetBuffer(PaWinWdmPin* pPin, void** pBuffer, DWORD* pRequestedBufSize, BOOL* pbCallMemBarrier)
  2064. {
  2065. PaError result = paNoError;
  2066. while (1)
  2067. {
  2068. if (pPin->pinKsSubType != SubType_kPolled)
  2069. {
  2070. /* In case of unknown (or notification), we try both modes */
  2071. result = PinGetBufferWithNotification(pPin, pBuffer, pRequestedBufSize, pbCallMemBarrier);
  2072. if (result == paNoError)
  2073. {
  2074. PA_DEBUG(("PinGetBuffer: SubType_kNotification\n"));
  2075. pPin->pinKsSubType = SubType_kNotification;
  2076. break;
  2077. }
  2078. }
  2079. result = PinGetBufferWithoutNotification(pPin, pBuffer, pRequestedBufSize, pbCallMemBarrier);
  2080. if (result == paNoError)
  2081. {
  2082. PA_DEBUG(("PinGetBuffer: SubType_kPolled\n"));
  2083. pPin->pinKsSubType = SubType_kPolled;
  2084. break;
  2085. }
  2086. /* Check if requested size is on a 128 byte boundary */
  2087. if (((*pRequestedBufSize) % 128UL) == 0)
  2088. {
  2089. PA_DEBUG(("Buffer size on 128 byte boundary, still fails :(\n"));
  2090. /* Ok, can't do much more */
  2091. break;
  2092. }
  2093. else
  2094. {
  2095. /* Compute LCM so we know which sizes are on a 128 byte boundary */
  2096. const unsigned gcd = PaWinWDMGCD(128UL, pPin->ksDataFormatWfx->WaveFormatEx.nBlockAlign);
  2097. const unsigned lcm = (128UL * pPin->ksDataFormatWfx->WaveFormatEx.nBlockAlign) / gcd;
  2098. DWORD dwOldSize = *pRequestedBufSize;
  2099. /* Align size to (next larger) LCM byte boundary, and then we try again. Note that LCM is not necessarily a
  2100. power of 2. */
  2101. *pRequestedBufSize = ((*pRequestedBufSize + lcm - 1) / lcm) * lcm;
  2102. PA_DEBUG(("Adjusting buffer size from %u to %u bytes (128 byte boundary, LCM=%u)\n", dwOldSize, *pRequestedBufSize, lcm));
  2103. }
  2104. }
  2105. return result;
  2106. }
  2107. static PaError PinRegisterPositionRegister(PaWinWdmPin* pPin)
  2108. {
  2109. PaError result = paNoError;
  2110. KSRTAUDIO_HWREGISTER_PROPERTY propIn;
  2111. KSRTAUDIO_HWREGISTER propOut;
  2112. PA_LOGE_;
  2113. propIn.BaseAddress = NULL;
  2114. propIn.Property.Set = KSPROPSETID_RtAudio;
  2115. propIn.Property.Id = KSPROPERTY_RTAUDIO_POSITIONREGISTER;
  2116. propIn.Property.Flags = KSPROPERTY_TYPE_GET;
  2117. result = WdmSyncIoctl(pPin->handle, IOCTL_KS_PROPERTY,
  2118. &propIn,
  2119. sizeof(KSRTAUDIO_HWREGISTER_PROPERTY),
  2120. &propOut,
  2121. sizeof(KSRTAUDIO_HWREGISTER),
  2122. NULL);
  2123. if (result == paNoError)
  2124. {
  2125. pPin->positionRegister = (ULONG*)propOut.Register;
  2126. }
  2127. else
  2128. {
  2129. PA_DEBUG(("Failed to register position register\n"));
  2130. }
  2131. PA_LOGL_;
  2132. return result;
  2133. }
  2134. static PaError PinRegisterNotificationHandle(PaWinWdmPin* pPin, HANDLE handle)
  2135. {
  2136. PaError result = paNoError;
  2137. KSRTAUDIO_NOTIFICATION_EVENT_PROPERTY prop;
  2138. PA_LOGE_;
  2139. prop.NotificationEvent = handle;
  2140. prop.Property.Set = KSPROPSETID_RtAudio;
  2141. prop.Property.Id = KSPROPERTY_RTAUDIO_REGISTER_NOTIFICATION_EVENT;
  2142. prop.Property.Flags = KSPROPERTY_TYPE_GET;
  2143. result = WdmSyncIoctl(pPin->handle,
  2144. IOCTL_KS_PROPERTY,
  2145. &prop,
  2146. sizeof(KSRTAUDIO_NOTIFICATION_EVENT_PROPERTY),
  2147. &prop,
  2148. sizeof(KSRTAUDIO_NOTIFICATION_EVENT_PROPERTY),
  2149. NULL);
  2150. if (result != paNoError) {
  2151. PA_DEBUG(("Failed to register notification handle 0x%08X\n", handle));
  2152. }
  2153. PA_LOGL_;
  2154. return result;
  2155. }
  2156. static PaError PinUnregisterNotificationHandle(PaWinWdmPin* pPin, HANDLE handle)
  2157. {
  2158. PaError result = paNoError;
  2159. KSRTAUDIO_NOTIFICATION_EVENT_PROPERTY prop;
  2160. PA_LOGE_;
  2161. if (handle != NULL)
  2162. {
  2163. prop.NotificationEvent = handle;
  2164. prop.Property.Set = KSPROPSETID_RtAudio;
  2165. prop.Property.Id = KSPROPERTY_RTAUDIO_UNREGISTER_NOTIFICATION_EVENT;
  2166. prop.Property.Flags = KSPROPERTY_TYPE_GET;
  2167. result = WdmSyncIoctl(pPin->handle,
  2168. IOCTL_KS_PROPERTY,
  2169. &prop,
  2170. sizeof(KSRTAUDIO_NOTIFICATION_EVENT_PROPERTY),
  2171. &prop,
  2172. sizeof(KSRTAUDIO_NOTIFICATION_EVENT_PROPERTY),
  2173. NULL);
  2174. if (result != paNoError) {
  2175. PA_DEBUG(("Failed to unregister notification handle 0x%08X\n", handle));
  2176. }
  2177. }
  2178. PA_LOGL_;
  2179. return result;
  2180. }
  2181. static PaError PinGetHwLatency(PaWinWdmPin* pPin, ULONG* pFifoSize, ULONG* pChipsetDelay, ULONG* pCodecDelay)
  2182. {
  2183. PaError result = paNoError;
  2184. KSPROPERTY propIn;
  2185. KSRTAUDIO_HWLATENCY propOut;
  2186. PA_LOGE_;
  2187. propIn.Set = KSPROPSETID_RtAudio;
  2188. propIn.Id = KSPROPERTY_RTAUDIO_HWLATENCY;
  2189. propIn.Flags = KSPROPERTY_TYPE_GET;
  2190. result = WdmSyncIoctl(pPin->handle, IOCTL_KS_PROPERTY,
  2191. &propIn,
  2192. sizeof(KSPROPERTY),
  2193. &propOut,
  2194. sizeof(KSRTAUDIO_HWLATENCY),
  2195. NULL);
  2196. if (result == paNoError)
  2197. {
  2198. *pFifoSize = propOut.FifoSize;
  2199. *pChipsetDelay = propOut.ChipsetDelay;
  2200. *pCodecDelay = propOut.CodecDelay;
  2201. }
  2202. else
  2203. {
  2204. PA_DEBUG(("Failed to retrieve hardware FIFO size!\n"));
  2205. }
  2206. PA_LOGL_;
  2207. return result;
  2208. }
  2209. /* This one is used for WaveRT */
  2210. static PaError PinGetAudioPositionDirect(PaWinWdmPin* pPin, ULONG* pPosition)
  2211. {
  2212. *pPosition = (*pPin->positionRegister);
  2213. return paNoError;
  2214. }
  2215. /* This one also, but in case the driver hasn't implemented memory mapped access to the position register */
  2216. static PaError PinGetAudioPositionViaIOCTL(PaWinWdmPin* pPin, ULONG* pPosition)
  2217. {
  2218. PaError result = paNoError;
  2219. KSPROPERTY propIn;
  2220. KSAUDIO_POSITION propOut;
  2221. PA_LOGE_;
  2222. propIn.Set = KSPROPSETID_Audio;
  2223. propIn.Id = KSPROPERTY_AUDIO_POSITION;
  2224. propIn.Flags = KSPROPERTY_TYPE_GET;
  2225. result = WdmSyncIoctl(pPin->handle,
  2226. IOCTL_KS_PROPERTY,
  2227. &propIn, sizeof(KSPROPERTY),
  2228. &propOut, sizeof(KSAUDIO_POSITION),
  2229. NULL);
  2230. if (result == paNoError)
  2231. {
  2232. *pPosition = (ULONG)(propOut.PlayOffset);
  2233. }
  2234. else
  2235. {
  2236. PA_DEBUG(("Failed to get audio position!\n"));
  2237. }
  2238. PA_LOGL_;
  2239. return result;
  2240. }
  2241. /***********************************************************************************************/
  2242. /**
  2243. * Create a new filter object.
  2244. */
  2245. static PaWinWdmFilter* FilterNew( PaWDMKSType type, DWORD devNode, const wchar_t* filterName, const wchar_t* friendlyName, PaError* error )
  2246. {
  2247. PaWinWdmFilter* filter = 0;
  2248. PaError result;
  2249. /* Allocate the new filter object */
  2250. filter = (PaWinWdmFilter*)PaUtil_AllocateMemory( sizeof(PaWinWdmFilter) );
  2251. if( !filter )
  2252. {
  2253. result = paInsufficientMemory;
  2254. goto error;
  2255. }
  2256. PA_DEBUG(("FilterNew: Creating filter '%S'\n", friendlyName));
  2257. /* Set type flag */
  2258. filter->devInfo.streamingType = type;
  2259. /* Store device node */
  2260. filter->deviceNode = devNode;
  2261. /* Zero the filter object - done by AllocateMemory */
  2262. /* memset( (void*)filter, 0, sizeof(PaWinWdmFilter) ); */
  2263. /* Copy the filter name */
  2264. wcsncpy(filter->devInfo.filterPath, filterName, MAX_PATH);
  2265. /* Copy the friendly name */
  2266. wcsncpy(filter->friendlyName, friendlyName, MAX_PATH);
  2267. PA_DEBUG(("FilterNew: Opening filter...\n", friendlyName));
  2268. /* Open the filter handle */
  2269. result = FilterUse(filter);
  2270. if( result != paNoError )
  2271. {
  2272. goto error;
  2273. }
  2274. /* Get pin count */
  2275. result = WdmGetPinPropertySimple
  2276. (
  2277. filter->handle,
  2278. 0,
  2279. &KSPROPSETID_Pin,
  2280. KSPROPERTY_PIN_CTYPES,
  2281. &filter->pinCount,
  2282. sizeof(filter->pinCount),
  2283. NULL);
  2284. if( result != paNoError)
  2285. {
  2286. goto error;
  2287. }
  2288. /* Get connections & nodes for filter */
  2289. result = WdmGetPropertyMulti(
  2290. filter->handle,
  2291. &KSPROPSETID_Topology,
  2292. KSPROPERTY_TOPOLOGY_CONNECTIONS,
  2293. &filter->connections);
  2294. if( result != paNoError)
  2295. {
  2296. goto error;
  2297. }
  2298. result = WdmGetPropertyMulti(
  2299. filter->handle,
  2300. &KSPROPSETID_Topology,
  2301. KSPROPERTY_TOPOLOGY_NODES,
  2302. &filter->nodes);
  2303. if( result != paNoError)
  2304. {
  2305. goto error;
  2306. }
  2307. /* For debugging purposes */
  2308. DumpConnectionsAndNodes(filter);
  2309. /* Get product GUID (it might not be supported) */
  2310. {
  2311. KSCOMPONENTID compId;
  2312. if (WdmGetPropertySimple(filter->handle, &KSPROPSETID_General, KSPROPERTY_GENERAL_COMPONENTID, &compId, sizeof(KSCOMPONENTID)) == paNoError)
  2313. {
  2314. filter->devInfo.deviceProductGuid = compId.Product;
  2315. }
  2316. }
  2317. /* This section is not executed for topology filters */
  2318. if (type != Type_kNotUsed)
  2319. {
  2320. /* Initialize the pins */
  2321. result = FilterInitializePins(filter);
  2322. if( result != paNoError)
  2323. {
  2324. goto error;
  2325. }
  2326. }
  2327. /* Close the filter handle for now
  2328. * It will be opened later when needed */
  2329. FilterRelease(filter);
  2330. *error = paNoError;
  2331. return filter;
  2332. error:
  2333. PA_DEBUG(("FilterNew: Error %d\n", result));
  2334. /*
  2335. Error cleanup
  2336. */
  2337. FilterFree(filter);
  2338. *error = result;
  2339. return NULL;
  2340. }
  2341. /**
  2342. * Add reference to filter
  2343. */
  2344. static void FilterAddRef( PaWinWdmFilter* filter )
  2345. {
  2346. if (filter != 0)
  2347. {
  2348. filter->filterRefCount++;
  2349. }
  2350. }
  2351. /**
  2352. * Initialize the pins of the filter. This is separated from FilterNew because this might fail if there is another
  2353. * process using the pin(s).
  2354. */
  2355. PaError FilterInitializePins( PaWinWdmFilter* filter )
  2356. {
  2357. PaError result = paNoError;
  2358. int pinId;
  2359. if (filter->devInfo.streamingType == Type_kNotUsed)
  2360. return paNoError;
  2361. if (filter->pins != NULL)
  2362. return paNoError;
  2363. /* Allocate pointer array to hold the pins */
  2364. filter->pins = (PaWinWdmPin**)PaUtil_AllocateMemory( sizeof(PaWinWdmPin*) * filter->pinCount );
  2365. if( !filter->pins )
  2366. {
  2367. result = paInsufficientMemory;
  2368. goto error;
  2369. }
  2370. /* Create all the pins we can */
  2371. for(pinId = 0; pinId < filter->pinCount; pinId++)
  2372. {
  2373. /* Create the pin with this Id */
  2374. PaWinWdmPin* newPin;
  2375. newPin = PinNew(filter, pinId, &result);
  2376. if( result == paInsufficientMemory )
  2377. goto error;
  2378. if( newPin != NULL )
  2379. {
  2380. filter->pins[pinId] = newPin;
  2381. ++filter->validPinCount;
  2382. }
  2383. }
  2384. if (filter->validPinCount == 0)
  2385. {
  2386. result = paDeviceUnavailable;
  2387. goto error;
  2388. }
  2389. return paNoError;
  2390. error:
  2391. if (filter->pins)
  2392. {
  2393. for (pinId = 0; pinId < filter->pinCount; ++pinId)
  2394. {
  2395. if (filter->pins[pinId])
  2396. {
  2397. PaUtil_FreeMemory(filter->pins[pinId]);
  2398. filter->pins[pinId] = 0;
  2399. }
  2400. }
  2401. PaUtil_FreeMemory( filter->pins );
  2402. filter->pins = 0;
  2403. }
  2404. return result;
  2405. }
  2406. /**
  2407. * Free a previously created filter
  2408. */
  2409. static void FilterFree(PaWinWdmFilter* filter)
  2410. {
  2411. int pinId;
  2412. PA_LOGL_;
  2413. if( filter )
  2414. {
  2415. if (--filter->filterRefCount > 0)
  2416. {
  2417. /* Ok, a stream has a ref count to this filter */
  2418. return;
  2419. }
  2420. if (filter->topologyFilter)
  2421. {
  2422. FilterFree(filter->topologyFilter);
  2423. filter->topologyFilter = 0;
  2424. }
  2425. if ( filter->pins )
  2426. {
  2427. for( pinId = 0; pinId < filter->pinCount; pinId++ )
  2428. PinFree(filter->pins[pinId]);
  2429. PaUtil_FreeMemory( filter->pins );
  2430. filter->pins = 0;
  2431. }
  2432. if( filter->connections )
  2433. {
  2434. PaUtil_FreeMemory(filter->connections);
  2435. filter->connections = 0;
  2436. }
  2437. if( filter->nodes )
  2438. {
  2439. PaUtil_FreeMemory(filter->nodes);
  2440. filter->nodes = 0;
  2441. }
  2442. if( filter->handle )
  2443. CloseHandle( filter->handle );
  2444. PaUtil_FreeMemory( filter );
  2445. }
  2446. PA_LOGE_;
  2447. }
  2448. /**
  2449. * Reopen the filter handle if necessary so it can be used
  2450. **/
  2451. static PaError FilterUse(PaWinWdmFilter* filter)
  2452. {
  2453. assert( filter );
  2454. PA_LOGE_;
  2455. if( filter->handle == NULL )
  2456. {
  2457. /* Open the filter */
  2458. filter->handle = CreateFileW(
  2459. filter->devInfo.filterPath,
  2460. GENERIC_READ | GENERIC_WRITE,
  2461. 0,
  2462. NULL,
  2463. OPEN_EXISTING,
  2464. FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED,
  2465. NULL);
  2466. if( filter->handle == NULL )
  2467. {
  2468. return paDeviceUnavailable;
  2469. }
  2470. }
  2471. filter->usageCount++;
  2472. PA_LOGL_;
  2473. return paNoError;
  2474. }
  2475. /**
  2476. * Release the filter handle if nobody is using it
  2477. **/
  2478. static void FilterRelease(PaWinWdmFilter* filter)
  2479. {
  2480. assert( filter );
  2481. assert( filter->usageCount > 0 );
  2482. PA_LOGE_;
  2483. /* Check first topology filter, if used */
  2484. if (filter->topologyFilter != NULL && filter->topologyFilter->handle != NULL)
  2485. {
  2486. FilterRelease(filter->topologyFilter);
  2487. }
  2488. filter->usageCount--;
  2489. if( filter->usageCount == 0 )
  2490. {
  2491. if( filter->handle != NULL )
  2492. {
  2493. CloseHandle( filter->handle );
  2494. filter->handle = NULL;
  2495. }
  2496. }
  2497. PA_LOGL_;
  2498. }
  2499. /**
  2500. * Create a render or playback pin using the supplied format
  2501. **/
  2502. static PaWinWdmPin* FilterCreatePin(PaWinWdmFilter* filter,
  2503. int pinId,
  2504. const WAVEFORMATEX* wfex,
  2505. PaError* error)
  2506. {
  2507. PaError result = paNoError;
  2508. PaWinWdmPin* pin = NULL;
  2509. assert( filter );
  2510. assert( pinId < filter->pinCount );
  2511. pin = filter->pins[pinId];
  2512. assert( pin );
  2513. result = PinSetFormat(pin,wfex);
  2514. if( result == paNoError )
  2515. {
  2516. result = PinInstantiate(pin);
  2517. }
  2518. *error = result;
  2519. return result == paNoError ? pin : 0;
  2520. }
  2521. static const wchar_t kUsbPrefix[] = L"\\\\?\\USB";
  2522. static BOOL IsUSBDevice(const wchar_t* devicePath)
  2523. {
  2524. /* Alex Lessard pointed out that different devices might present the device path with
  2525. lower case letters. */
  2526. return (_wcsnicmp(devicePath, kUsbPrefix, sizeof(kUsbPrefix)/sizeof(kUsbPrefix[0]) ) == 0);
  2527. }
  2528. /* This should make it more language tolerant, I hope... */
  2529. static const wchar_t kUsbNamePrefix[] = L"USB Audio";
  2530. static BOOL IsNameUSBAudioDevice(const wchar_t* friendlyName)
  2531. {
  2532. return (_wcsnicmp(friendlyName, kUsbNamePrefix, sizeof(kUsbNamePrefix)/sizeof(kUsbNamePrefix[0])) == 0);
  2533. }
  2534. typedef enum _tag_EAlias
  2535. {
  2536. Alias_kRender = (1<<0),
  2537. Alias_kCapture = (1<<1),
  2538. Alias_kRealtime = (1<<2),
  2539. } EAlias;
  2540. /* Trim whitespace from string */
  2541. static void TrimString(wchar_t* str, size_t length)
  2542. {
  2543. wchar_t* s = str;
  2544. wchar_t* e = 0;
  2545. /* Find start of string */
  2546. while (iswspace(*s)) ++s;
  2547. e=s+min(length,wcslen(s))-1;
  2548. /* Find end of string */
  2549. while(e>s && iswspace(*e)) --e;
  2550. ++e;
  2551. length = e - s;
  2552. memmove(str, s, length * sizeof(wchar_t));
  2553. str[length] = 0;
  2554. }
  2555. /**
  2556. * Build the list of available filters
  2557. * Use the SetupDi API to enumerate all devices in the KSCATEGORY_AUDIO which
  2558. * have a KSCATEGORY_RENDER or KSCATEGORY_CAPTURE alias. For each of these
  2559. * devices initialise a PaWinWdmFilter structure by calling our NewFilter()
  2560. * function. We enumerate devices twice, once to count how many there are,
  2561. * and once to initialize the PaWinWdmFilter structures.
  2562. *
  2563. * Vista and later: Also check KSCATEGORY_REALTIME for WaveRT devices.
  2564. */
  2565. //PaError BuildFilterList( PaWinWdmHostApiRepresentation* wdmHostApi, int* noOfPaDevices )
  2566. PaWinWdmFilter** BuildFilterList( int* pFilterCount, int* pNoOfPaDevices, PaError* pResult )
  2567. {
  2568. PaWinWdmFilter** ppFilters = NULL;
  2569. HDEVINFO handle = NULL;
  2570. int device;
  2571. int invalidDevices;
  2572. int slot;
  2573. SP_DEVICE_INTERFACE_DATA interfaceData;
  2574. SP_DEVICE_INTERFACE_DATA aliasData;
  2575. SP_DEVINFO_DATA devInfoData;
  2576. int noError;
  2577. const int sizeInterface = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA) + (MAX_PATH * sizeof(WCHAR));
  2578. unsigned char interfaceDetailsArray[sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA) + (MAX_PATH * sizeof(WCHAR))];
  2579. SP_DEVICE_INTERFACE_DETAIL_DATA_W* devInterfaceDetails = (SP_DEVICE_INTERFACE_DETAIL_DATA_W*)interfaceDetailsArray;
  2580. const GUID* category = (const GUID*)&KSCATEGORY_AUDIO;
  2581. const GUID* alias_render = (const GUID*)&KSCATEGORY_RENDER;
  2582. const GUID* alias_capture = (const GUID*)&KSCATEGORY_CAPTURE;
  2583. const GUID* category_realtime = (const GUID*)&KSCATEGORY_REALTIME;
  2584. DWORD aliasFlags;
  2585. PaWDMKSType streamingType;
  2586. int filterCount = 0;
  2587. int noOfPaDevices = 0;
  2588. PA_LOGE_;
  2589. assert(pFilterCount != NULL);
  2590. assert(pNoOfPaDevices != NULL);
  2591. assert(pResult != NULL);
  2592. devInterfaceDetails->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W);
  2593. *pFilterCount = 0;
  2594. *pNoOfPaDevices = 0;
  2595. /* Open a handle to search for devices (filters) */
  2596. handle = SetupDiGetClassDevs(category,NULL,NULL,DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);
  2597. if( handle == INVALID_HANDLE_VALUE )
  2598. {
  2599. *pResult = paUnanticipatedHostError;
  2600. return NULL;
  2601. }
  2602. PA_DEBUG(("Setup called\n"));
  2603. /* First let's count the number of devices so we can allocate a list */
  2604. invalidDevices = 0;
  2605. for( device = 0;;device++ )
  2606. {
  2607. interfaceData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
  2608. interfaceData.Reserved = 0;
  2609. aliasData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
  2610. aliasData.Reserved = 0;
  2611. noError = SetupDiEnumDeviceInterfaces(handle,NULL,category,device,&interfaceData);
  2612. PA_DEBUG(("Enum called\n"));
  2613. if( !noError )
  2614. break; /* No more devices */
  2615. /* Check this one has the render or capture alias */
  2616. aliasFlags = 0;
  2617. noError = SetupDiGetDeviceInterfaceAlias(handle,&interfaceData,alias_render,&aliasData);
  2618. PA_DEBUG(("noError = %d\n",noError));
  2619. if(noError)
  2620. {
  2621. if(aliasData.Flags && (!(aliasData.Flags & SPINT_REMOVED)))
  2622. {
  2623. PA_DEBUG(("Device %d has render alias\n",device));
  2624. aliasFlags |= Alias_kRender; /* Has render alias */
  2625. }
  2626. else
  2627. {
  2628. PA_DEBUG(("Device %d has no render alias\n",device));
  2629. }
  2630. }
  2631. noError = SetupDiGetDeviceInterfaceAlias(handle,&interfaceData,alias_capture,&aliasData);
  2632. if(noError)
  2633. {
  2634. if(aliasData.Flags && (!(aliasData.Flags & SPINT_REMOVED)))
  2635. {
  2636. PA_DEBUG(("Device %d has capture alias\n",device));
  2637. aliasFlags |= Alias_kCapture; /* Has capture alias */
  2638. }
  2639. else
  2640. {
  2641. PA_DEBUG(("Device %d has no capture alias\n",device));
  2642. }
  2643. }
  2644. if(!aliasFlags)
  2645. invalidDevices++; /* This was not a valid capture or render audio device */
  2646. }
  2647. /* Remember how many there are */
  2648. filterCount = device-invalidDevices;
  2649. PA_DEBUG(("Interfaces found: %d\n",device-invalidDevices));
  2650. /* Now allocate the list of pointers to devices */
  2651. ppFilters = (PaWinWdmFilter**)PaUtil_AllocateMemory( sizeof(PaWinWdmFilter*) * filterCount);
  2652. if( ppFilters == 0 )
  2653. {
  2654. if(handle != NULL)
  2655. SetupDiDestroyDeviceInfoList(handle);
  2656. *pResult = paInsufficientMemory;
  2657. return NULL;
  2658. }
  2659. /* Now create filter objects for each interface found */
  2660. slot = 0;
  2661. for( device = 0;;device++ )
  2662. {
  2663. interfaceData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
  2664. interfaceData.Reserved = 0;
  2665. aliasData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
  2666. aliasData.Reserved = 0;
  2667. devInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
  2668. devInfoData.Reserved = 0;
  2669. streamingType = Type_kWaveCyclic;
  2670. noError = SetupDiEnumDeviceInterfaces(handle,NULL,category,device,&interfaceData);
  2671. if( !noError )
  2672. break; /* No more devices */
  2673. /* Check this one has the render or capture alias */
  2674. aliasFlags = 0;
  2675. noError = SetupDiGetDeviceInterfaceAlias(handle,&interfaceData,alias_render,&aliasData);
  2676. if(noError)
  2677. {
  2678. if(aliasData.Flags && (!(aliasData.Flags & SPINT_REMOVED)))
  2679. {
  2680. PA_DEBUG(("Device %d has render alias\n",device));
  2681. aliasFlags |= Alias_kRender; /* Has render alias */
  2682. }
  2683. }
  2684. noError = SetupDiGetDeviceInterfaceAlias(handle,&interfaceData,alias_capture,&aliasData);
  2685. if(noError)
  2686. {
  2687. if(aliasData.Flags && (!(aliasData.Flags & SPINT_REMOVED)))
  2688. {
  2689. PA_DEBUG(("Device %d has capture alias\n",device));
  2690. aliasFlags |= Alias_kCapture; /* Has capture alias */
  2691. }
  2692. }
  2693. if(!aliasFlags)
  2694. {
  2695. continue; /* This was not a valid capture or render audio device */
  2696. }
  2697. else
  2698. {
  2699. /* Check if filter is WaveRT, if not it is a WaveCyclic */
  2700. noError = SetupDiGetDeviceInterfaceAlias(handle,&interfaceData,category_realtime,&aliasData);
  2701. if (noError)
  2702. {
  2703. PA_DEBUG(("Device %d has realtime alias\n",device));
  2704. aliasFlags |= Alias_kRealtime;
  2705. streamingType = Type_kWaveRT;
  2706. }
  2707. }
  2708. noError = SetupDiGetDeviceInterfaceDetailW(handle,&interfaceData,devInterfaceDetails,sizeInterface,NULL,&devInfoData);
  2709. if( noError )
  2710. {
  2711. DWORD type;
  2712. WCHAR friendlyName[MAX_PATH] = {0};
  2713. DWORD sizeFriendlyName;
  2714. PaWinWdmFilter* newFilter = 0;
  2715. PaError result = paNoError;
  2716. /* Try to get the "friendly name" for this interface */
  2717. sizeFriendlyName = sizeof(friendlyName);
  2718. if (IsEarlierThanVista() && IsUSBDevice(devInterfaceDetails->DevicePath))
  2719. {
  2720. /* XP and USB audio device needs to look elsewhere, otherwise it'll only be a "USB Audio Device". Not
  2721. very literate. */
  2722. if (!SetupDiGetDeviceRegistryPropertyW(handle,
  2723. &devInfoData,
  2724. SPDRP_LOCATION_INFORMATION,
  2725. &type,
  2726. (BYTE*)friendlyName,
  2727. sizeof(friendlyName),
  2728. NULL))
  2729. {
  2730. friendlyName[0] = 0;
  2731. }
  2732. }
  2733. if (friendlyName[0] == 0 || IsNameUSBAudioDevice(friendlyName))
  2734. {
  2735. /* Fix contributed by Ben Allison
  2736. * Removed KEY_SET_VALUE from flags on following call
  2737. * as its causes failure when running without admin rights
  2738. * and it was not required */
  2739. HKEY hkey=SetupDiOpenDeviceInterfaceRegKey(handle,&interfaceData,0,KEY_QUERY_VALUE);
  2740. if(hkey!=INVALID_HANDLE_VALUE)
  2741. {
  2742. noError = RegQueryValueExW(hkey,L"FriendlyName",0,&type,(BYTE*)friendlyName,&sizeFriendlyName);
  2743. if( noError == ERROR_SUCCESS )
  2744. {
  2745. PA_DEBUG(("Interface %d, Name: %s\n",device,friendlyName));
  2746. RegCloseKey(hkey);
  2747. }
  2748. else
  2749. {
  2750. friendlyName[0] = 0;
  2751. }
  2752. }
  2753. }
  2754. TrimString(friendlyName, sizeFriendlyName);
  2755. newFilter = FilterNew(streamingType,
  2756. devInfoData.DevInst,
  2757. devInterfaceDetails->DevicePath,
  2758. friendlyName,
  2759. &result);
  2760. if( result == paNoError )
  2761. {
  2762. int pin;
  2763. unsigned filterIOs = 0;
  2764. /* Increment number of "devices" */
  2765. for (pin = 0; pin < newFilter->pinCount; ++pin)
  2766. {
  2767. PaWinWdmPin* pPin = newFilter->pins[pin];
  2768. if (pPin == NULL)
  2769. continue;
  2770. filterIOs += max(1, pPin->inputCount);
  2771. }
  2772. noOfPaDevices += filterIOs;
  2773. PA_DEBUG(("Filter (%s) created with %d valid pins (total I/Os: %u)\n", ((newFilter->devInfo.streamingType==Type_kWaveRT)?"WaveRT":"WaveCyclic"), newFilter->validPinCount, filterIOs));
  2774. assert(slot < filterCount);
  2775. ppFilters[slot] = newFilter;
  2776. slot++;
  2777. }
  2778. else
  2779. {
  2780. PA_DEBUG(("Filter NOT created\n"));
  2781. /* As there are now less filters than we initially thought
  2782. * we must reduce the count by one */
  2783. filterCount--;
  2784. }
  2785. }
  2786. }
  2787. /* Clean up */
  2788. if(handle != NULL)
  2789. SetupDiDestroyDeviceInfoList(handle);
  2790. *pFilterCount = filterCount;
  2791. *pNoOfPaDevices = noOfPaDevices;
  2792. return ppFilters;
  2793. }
  2794. typedef struct PaNameHashIndex
  2795. {
  2796. unsigned index;
  2797. unsigned count;
  2798. ULONG hash;
  2799. struct PaNameHashIndex *next;
  2800. } PaNameHashIndex;
  2801. typedef struct PaNameHashObject
  2802. {
  2803. PaNameHashIndex* list;
  2804. PaUtilAllocationGroup* allocGroup;
  2805. } PaNameHashObject;
  2806. static ULONG GetNameHash(const wchar_t* str, const BOOL input)
  2807. {
  2808. /* This is to make sure that a name that exists as both input & output won't get the same hash value */
  2809. const ULONG fnv_prime = (input ? 0x811C9DD7 : 0x811FEB0B);
  2810. ULONG hash = 0;
  2811. for(; *str != 0; str++)
  2812. {
  2813. hash *= fnv_prime;
  2814. hash ^= (*str);
  2815. }
  2816. assert(hash != 0);
  2817. return hash;
  2818. }
  2819. static PaError CreateHashEntry(PaNameHashObject* obj, const wchar_t* name, const BOOL input)
  2820. {
  2821. ULONG hash = GetNameHash(name, input);
  2822. PaNameHashIndex * pLast = NULL;
  2823. PaNameHashIndex * p = obj->list;
  2824. while (p != 0)
  2825. {
  2826. if (p->hash == hash)
  2827. {
  2828. break;
  2829. }
  2830. pLast = p;
  2831. p = p->next;
  2832. }
  2833. if (p == NULL)
  2834. {
  2835. p = (PaNameHashIndex*)PaUtil_GroupAllocateMemory(obj->allocGroup, sizeof(PaNameHashIndex));
  2836. if (p == NULL)
  2837. {
  2838. return paInsufficientMemory;
  2839. }
  2840. p->hash = hash;
  2841. p->count = 1;
  2842. if (pLast != 0)
  2843. {
  2844. assert(pLast->next == 0);
  2845. pLast->next = p;
  2846. }
  2847. if (obj->list == 0)
  2848. {
  2849. obj->list = p;
  2850. }
  2851. }
  2852. else
  2853. {
  2854. ++p->count;
  2855. }
  2856. return paNoError;
  2857. }
  2858. static PaError InitNameHashObject(PaNameHashObject* obj, PaWinWdmFilter* pFilter)
  2859. {
  2860. int i;
  2861. obj->allocGroup = PaUtil_CreateAllocationGroup();
  2862. if (obj->allocGroup == NULL)
  2863. {
  2864. return paInsufficientMemory;
  2865. }
  2866. for (i = 0; i < pFilter->pinCount; ++i)
  2867. {
  2868. unsigned m;
  2869. PaWinWdmPin* pin = pFilter->pins[i];
  2870. if (pin == NULL)
  2871. continue;
  2872. for (m = 0; m < max(1, pin->inputCount); ++m)
  2873. {
  2874. const BOOL isInput = (pin->dataFlow == KSPIN_DATAFLOW_OUT);
  2875. const wchar_t* name = (pin->inputs == NULL) ? pin->friendlyName : pin->inputs[m]->friendlyName;
  2876. PaError result = CreateHashEntry(obj, name, isInput);
  2877. if (result != paNoError)
  2878. {
  2879. return result;
  2880. }
  2881. }
  2882. }
  2883. return paNoError;
  2884. }
  2885. static void DeinitNameHashObject(PaNameHashObject* obj)
  2886. {
  2887. assert(obj != 0);
  2888. PaUtil_FreeAllAllocations(obj->allocGroup);
  2889. PaUtil_DestroyAllocationGroup(obj->allocGroup);
  2890. memset(obj, 0, sizeof(PaNameHashObject));
  2891. }
  2892. static unsigned GetNameIndex(PaNameHashObject* obj, const wchar_t* name, const BOOL input)
  2893. {
  2894. ULONG hash = GetNameHash(name, input);
  2895. PaNameHashIndex* p = obj->list;
  2896. while (p != NULL)
  2897. {
  2898. if (p->hash == hash)
  2899. {
  2900. if (p->count > 1)
  2901. {
  2902. return (++p->index);
  2903. }
  2904. else
  2905. {
  2906. return 0;
  2907. }
  2908. }
  2909. p = p->next;
  2910. }
  2911. // Should never get here!!
  2912. assert(FALSE);
  2913. return 0;
  2914. }
  2915. static PaError ScanDeviceInfos( struct PaUtilHostApiRepresentation *hostApi, PaHostApiIndex hostApiIndex, void **scanResults, int *newDeviceCount )
  2916. {
  2917. PaWinWdmHostApiRepresentation *wdmHostApi = (PaWinWdmHostApiRepresentation*)hostApi;
  2918. PaError result = paNoError;
  2919. PaWinWdmFilter** ppFilters = 0;
  2920. PaWinWDMScanDeviceInfosResults *outArgument = 0;
  2921. int filterCount = 0;
  2922. int totalDeviceCount = 0;
  2923. int idxDevice = 0;
  2924. ppFilters = BuildFilterList( &filterCount, &totalDeviceCount, &result );
  2925. if( result != paNoError )
  2926. {
  2927. goto error;
  2928. }
  2929. if( totalDeviceCount > 0 )
  2930. {
  2931. PaWinWdmDeviceInfo *deviceInfoArray = 0;
  2932. int idxFilter;
  2933. int i;
  2934. /* Allocate the out param for all the info we need */
  2935. outArgument = (PaWinWDMScanDeviceInfosResults *) PaUtil_GroupAllocateMemory(
  2936. wdmHostApi->allocations, sizeof(PaWinWDMScanDeviceInfosResults) );
  2937. if( !outArgument )
  2938. {
  2939. result = paInsufficientMemory;
  2940. goto error;
  2941. }
  2942. outArgument->defaultInputDevice = paNoDevice;
  2943. outArgument->defaultOutputDevice = paNoDevice;
  2944. outArgument->deviceInfos = (PaDeviceInfo**)PaUtil_GroupAllocateMemory(
  2945. wdmHostApi->allocations, sizeof(PaDeviceInfo*) * totalDeviceCount );
  2946. if( !outArgument->deviceInfos )
  2947. {
  2948. result = paInsufficientMemory;
  2949. goto error;
  2950. }
  2951. /* allocate all device info structs in a contiguous block */
  2952. deviceInfoArray = (PaWinWdmDeviceInfo*)PaUtil_GroupAllocateMemory(
  2953. wdmHostApi->allocations, sizeof(PaWinWdmDeviceInfo) * totalDeviceCount );
  2954. if( !deviceInfoArray )
  2955. {
  2956. result = paInsufficientMemory;
  2957. goto error;
  2958. }
  2959. /* Make sure all items in array */
  2960. for( i = 0 ; i < totalDeviceCount; ++i )
  2961. {
  2962. PaDeviceInfo *deviceInfo = &deviceInfoArray[i].inheritedDeviceInfo;
  2963. deviceInfo->structVersion = 2;
  2964. deviceInfo->hostApi = hostApiIndex;
  2965. deviceInfo->name = 0;
  2966. outArgument->deviceInfos[ i ] = deviceInfo;
  2967. }
  2968. idxDevice = 0;
  2969. for (idxFilter = 0; idxFilter < filterCount; ++idxFilter)
  2970. {
  2971. PaNameHashObject nameHash = {0};
  2972. PaWinWdmFilter* pFilter = ppFilters[idxFilter];
  2973. if( pFilter == NULL )
  2974. continue;
  2975. if (InitNameHashObject(&nameHash, pFilter) != paNoError)
  2976. {
  2977. DeinitNameHashObject(&nameHash);
  2978. continue;
  2979. }
  2980. for (i = 0; i < pFilter->pinCount; ++i)
  2981. {
  2982. unsigned m;
  2983. ULONG nameIndex = 0;
  2984. ULONG nameIndexHash = 0;
  2985. PaWinWdmPin* pin = pFilter->pins[i];
  2986. if (pin == NULL)
  2987. continue;
  2988. for (m = 0; m < max(1, pin->inputCount); ++m)
  2989. {
  2990. PaWinWdmDeviceInfo *wdmDeviceInfo = (PaWinWdmDeviceInfo *)outArgument->deviceInfos[idxDevice];
  2991. PaDeviceInfo *deviceInfo = &wdmDeviceInfo->inheritedDeviceInfo;
  2992. wchar_t localCompositeName[MAX_PATH];
  2993. unsigned nameIndex = 0;
  2994. const BOOL isInput = (pin->dataFlow == KSPIN_DATAFLOW_OUT);
  2995. wdmDeviceInfo->filter = pFilter;
  2996. deviceInfo->structVersion = 2;
  2997. deviceInfo->hostApi = hostApiIndex;
  2998. deviceInfo->name = wdmDeviceInfo->compositeName;
  2999. /* deviceInfo->hostApiSpecificDeviceInfo = &pFilter->devInfo; */
  3000. wdmDeviceInfo->pin = pin->pinId;
  3001. /* Get the name of the "device" */
  3002. if (pin->inputs == NULL)
  3003. {
  3004. wcsncpy(localCompositeName, pin->friendlyName, MAX_PATH);
  3005. wdmDeviceInfo->muxPosition = -1;
  3006. wdmDeviceInfo->endpointPinId = pin->endpointPinId;
  3007. }
  3008. else
  3009. {
  3010. PaWinWdmMuxedInput* input = pin->inputs[m];
  3011. wcsncpy(localCompositeName, input->friendlyName, MAX_PATH);
  3012. wdmDeviceInfo->muxPosition = (int)m;
  3013. wdmDeviceInfo->endpointPinId = input->endpointPinId;
  3014. }
  3015. {
  3016. /* Get base length */
  3017. size_t n = wcslen(localCompositeName);
  3018. /* Check if there are more entries with same name (which might very well be the case), if there
  3019. are, the name will be postfixed with an index. */
  3020. nameIndex = GetNameIndex(&nameHash, localCompositeName, isInput);
  3021. if (nameIndex > 0)
  3022. {
  3023. /* This name has multiple instances, so we post fix with a number */
  3024. n += _snwprintf(localCompositeName + n, MAX_PATH - n, L" %u", nameIndex);
  3025. }
  3026. /* Postfix with filter name */
  3027. _snwprintf(localCompositeName + n, MAX_PATH - n, L" (%s)", pFilter->friendlyName);
  3028. }
  3029. /* Convert wide char string to utf-8 */
  3030. WideCharToMultiByte(CP_UTF8, 0, localCompositeName, -1, wdmDeviceInfo->compositeName, MAX_PATH, NULL, NULL);
  3031. /* NB! WDM/KS has no concept of a full-duplex device, each pin is either an input or and output */
  3032. if (isInput)
  3033. {
  3034. /* INPUT ! */
  3035. deviceInfo->maxInputChannels = pin->maxChannels;
  3036. deviceInfo->maxOutputChannels = 0;
  3037. if (outArgument->defaultInputDevice == paNoDevice)
  3038. {
  3039. outArgument->defaultInputDevice = idxDevice;
  3040. }
  3041. }
  3042. else
  3043. {
  3044. /* OUTPUT ! */
  3045. deviceInfo->maxInputChannels = 0;
  3046. deviceInfo->maxOutputChannels = pin->maxChannels;
  3047. if (outArgument->defaultOutputDevice == paNoDevice)
  3048. {
  3049. outArgument->defaultOutputDevice = idxDevice;
  3050. }
  3051. }
  3052. /* These low values are not very useful because
  3053. * a) The lowest latency we end up with can depend on many factors such
  3054. * as the device buffer sizes/granularities, sample rate, channels and format
  3055. * b) We cannot know the device buffer sizes until we try to open/use it at
  3056. * a particular setting
  3057. * So: we give 512x48000Hz frames as the default low input latency
  3058. **/
  3059. switch (pFilter->devInfo.streamingType)
  3060. {
  3061. case Type_kWaveCyclic:
  3062. if (IsEarlierThanVista())
  3063. {
  3064. /* XP doesn't tolerate low latency, unless the Process Priority Class is set to REALTIME_PRIORITY_CLASS
  3065. through SetPriorityClass, then 10 ms is quite feasible. However, one should then bear in mind that ALL of
  3066. the process is running in REALTIME_PRIORITY_CLASS, which might not be appropriate for an application with
  3067. a GUI . In this case it is advisable to separate the audio engine in another process and use IPC to communicate
  3068. with it. */
  3069. deviceInfo->defaultLowInputLatency = 0.02;
  3070. deviceInfo->defaultLowOutputLatency = 0.02;
  3071. }
  3072. else
  3073. {
  3074. /* This is a conservative estimate. Most WaveCyclic drivers will limit the available latency, but f.i. my Edirol
  3075. PCR-A30 can reach 3 ms latency easily... */
  3076. deviceInfo->defaultLowInputLatency = 0.01;
  3077. deviceInfo->defaultLowOutputLatency = 0.01;
  3078. }
  3079. deviceInfo->defaultHighInputLatency = (4096.0/48000.0);
  3080. deviceInfo->defaultHighOutputLatency = (4096.0/48000.0);
  3081. deviceInfo->defaultSampleRate = (double)(pin->defaultSampleRate);
  3082. break;
  3083. case Type_kWaveRT:
  3084. /* This is also a conservative estimate, based on WaveRT polled mode. In polled mode, the latency will be dictated
  3085. by the buffer size given by the driver. */
  3086. deviceInfo->defaultLowInputLatency = 0.01;
  3087. deviceInfo->defaultLowOutputLatency = 0.01;
  3088. deviceInfo->defaultHighInputLatency = 0.04;
  3089. deviceInfo->defaultHighOutputLatency = 0.04;
  3090. deviceInfo->defaultSampleRate = (double)(pin->defaultSampleRate);
  3091. break;
  3092. default:
  3093. assert(0);
  3094. break;
  3095. }
  3096. /* Add reference to filter */
  3097. FilterAddRef(wdmDeviceInfo->filter);
  3098. assert(idxDevice < totalDeviceCount);
  3099. ++idxDevice;
  3100. }
  3101. }
  3102. /* If no one has add ref'd the filter, drop it */
  3103. if (pFilter->filterRefCount == 0)
  3104. {
  3105. FilterFree(pFilter);
  3106. }
  3107. /* Deinitialize name hash object */
  3108. DeinitNameHashObject(&nameHash);
  3109. }
  3110. }
  3111. *scanResults = outArgument;
  3112. *newDeviceCount = idxDevice;
  3113. return result;
  3114. error:
  3115. result = DisposeDeviceInfos(hostApi, outArgument, totalDeviceCount);
  3116. return result;
  3117. }
  3118. static PaError CommitDeviceInfos( struct PaUtilHostApiRepresentation *hostApi, PaHostApiIndex index, void *scanResults, int deviceCount )
  3119. {
  3120. PaWinWdmHostApiRepresentation *wdmHostApi = (PaWinWdmHostApiRepresentation*)hostApi;
  3121. hostApi->info.deviceCount = 0;
  3122. hostApi->info.defaultInputDevice = paNoDevice;
  3123. hostApi->info.defaultOutputDevice = paNoDevice;
  3124. /* Free any old memory which might be in the device info */
  3125. if( hostApi->deviceInfos )
  3126. {
  3127. PaWinWDMScanDeviceInfosResults* localScanResults = (PaWinWDMScanDeviceInfosResults*)PaUtil_GroupAllocateMemory(
  3128. wdmHostApi->allocations, sizeof(PaWinWDMScanDeviceInfosResults));
  3129. localScanResults->deviceInfos = hostApi->deviceInfos;
  3130. DisposeDeviceInfos(hostApi, &localScanResults, hostApi->info.deviceCount);
  3131. hostApi->deviceInfos = NULL;
  3132. }
  3133. if( scanResults != NULL )
  3134. {
  3135. PaWinWDMScanDeviceInfosResults *scanDeviceInfosResults = ( PaWinWDMScanDeviceInfosResults * ) scanResults;
  3136. if( deviceCount > 0 )
  3137. {
  3138. /* use the array allocated in ScanDeviceInfos() as our deviceInfos */
  3139. hostApi->deviceInfos = scanDeviceInfosResults->deviceInfos;
  3140. hostApi->info.defaultInputDevice = scanDeviceInfosResults->defaultInputDevice;
  3141. hostApi->info.defaultOutputDevice = scanDeviceInfosResults->defaultOutputDevice;
  3142. hostApi->info.deviceCount = deviceCount;
  3143. }
  3144. PaUtil_GroupFreeMemory( wdmHostApi->allocations, scanDeviceInfosResults );
  3145. }
  3146. return paNoError;
  3147. }
  3148. static PaError DisposeDeviceInfos( struct PaUtilHostApiRepresentation *hostApi, void *scanResults, int deviceCount )
  3149. {
  3150. PaWinWdmHostApiRepresentation *winDsHostApi = (PaWinWdmHostApiRepresentation*)hostApi;
  3151. if( scanResults != NULL )
  3152. {
  3153. PaWinWDMScanDeviceInfosResults *scanDeviceInfosResults = ( PaWinWDMScanDeviceInfosResults * ) scanResults;
  3154. if( scanDeviceInfosResults->deviceInfos )
  3155. {
  3156. int i;
  3157. for (i = 0; i < deviceCount; ++i)
  3158. {
  3159. PaWinWdmDeviceInfo* pDevice = (PaWinWdmDeviceInfo*)scanDeviceInfosResults->deviceInfos[i];
  3160. if (pDevice->filter != 0)
  3161. {
  3162. FilterFree(pDevice->filter);
  3163. }
  3164. }
  3165. PaUtil_GroupFreeMemory( winDsHostApi->allocations, scanDeviceInfosResults->deviceInfos[0] ); /* all device info structs are allocated in a block so we can destroy them here */
  3166. PaUtil_GroupFreeMemory( winDsHostApi->allocations, scanDeviceInfosResults->deviceInfos );
  3167. }
  3168. PaUtil_GroupFreeMemory( winDsHostApi->allocations, scanDeviceInfosResults );
  3169. }
  3170. return paNoError;
  3171. }
  3172. PaError PaWinWdm_Initialize( PaUtilHostApiRepresentation **hostApi, PaHostApiIndex hostApiIndex )
  3173. {
  3174. PaError result = paNoError;
  3175. int deviceCount = 0;
  3176. void *scanResults = 0;
  3177. PaWinWdmHostApiRepresentation *wdmHostApi = NULL;
  3178. PA_LOGE_;
  3179. #ifdef PA_WDMKS_SET_TREF
  3180. tRef = PaUtil_GetTime();
  3181. #endif
  3182. /*
  3183. Attempt to load the KSUSER.DLL without which we cannot create pins
  3184. We will unload this on termination
  3185. */
  3186. if(DllKsUser == NULL)
  3187. {
  3188. DllKsUser = LoadLibrary(TEXT("ksuser.dll"));
  3189. if(DllKsUser == NULL)
  3190. goto error;
  3191. }
  3192. FunctionKsCreatePin = (KSCREATEPIN*)GetProcAddress(DllKsUser, "KsCreatePin");
  3193. if(FunctionKsCreatePin == NULL)
  3194. goto error;
  3195. /* Attempt to load AVRT.DLL, if we can't, then we'll just use time critical prio instead... */
  3196. if(paWinWDMKSAvRtEntryPoints.hInstance == NULL)
  3197. {
  3198. paWinWDMKSAvRtEntryPoints.hInstance = LoadLibrary(TEXT("avrt.dll"));
  3199. if (paWinWDMKSAvRtEntryPoints.hInstance != NULL)
  3200. {
  3201. paWinWDMKSAvRtEntryPoints.AvSetMmThreadCharacteristics =
  3202. (HANDLE(WINAPI*)(LPCSTR,LPDWORD))GetProcAddress(paWinWDMKSAvRtEntryPoints.hInstance,"AvSetMmThreadCharacteristicsA");
  3203. paWinWDMKSAvRtEntryPoints.AvRevertMmThreadCharacteristics =
  3204. (BOOL(WINAPI*)(HANDLE))GetProcAddress(paWinWDMKSAvRtEntryPoints.hInstance, "AvRevertMmThreadCharacteristics");
  3205. paWinWDMKSAvRtEntryPoints.AvSetMmThreadPriority =
  3206. (BOOL(WINAPI*)(HANDLE,PA_AVRT_PRIORITY))GetProcAddress(paWinWDMKSAvRtEntryPoints.hInstance, "AvSetMmThreadPriority");
  3207. }
  3208. }
  3209. wdmHostApi = (PaWinWdmHostApiRepresentation*)PaUtil_AllocateMemory( sizeof(PaWinWdmHostApiRepresentation) );
  3210. if( !wdmHostApi )
  3211. {
  3212. result = paInsufficientMemory;
  3213. goto error;
  3214. }
  3215. wdmHostApi->allocations = PaUtil_CreateAllocationGroup();
  3216. if( !wdmHostApi->allocations )
  3217. {
  3218. result = paInsufficientMemory;
  3219. goto error;
  3220. }
  3221. *hostApi = &wdmHostApi->inheritedHostApiRep;
  3222. (*hostApi)->info.structVersion = 1;
  3223. (*hostApi)->info.type = paWDMKS;
  3224. (*hostApi)->info.name = "Windows WDM-KS";
  3225. /* these are all updated by CommitDeviceInfos() */
  3226. (*hostApi)->info.deviceCount = 0;
  3227. (*hostApi)->info.defaultInputDevice = paNoDevice;
  3228. (*hostApi)->info.defaultOutputDevice = paNoDevice;
  3229. (*hostApi)->deviceInfos = 0;
  3230. result = ScanDeviceInfos(&wdmHostApi->inheritedHostApiRep, hostApiIndex, &scanResults, &deviceCount);
  3231. if (result != paNoError)
  3232. {
  3233. goto error;
  3234. }
  3235. CommitDeviceInfos(&wdmHostApi->inheritedHostApiRep, hostApiIndex, scanResults, deviceCount);
  3236. (*hostApi)->Terminate = Terminate;
  3237. (*hostApi)->OpenStream = OpenStream;
  3238. (*hostApi)->IsFormatSupported = IsFormatSupported;
  3239. /* In preparation for hotplug
  3240. (*hostApi)->ScanDeviceInfos = ScanDeviceInfos;
  3241. (*hostApi)->CommitDeviceInfos = CommitDeviceInfos;
  3242. (*hostApi)->DisposeDeviceInfos = DisposeDeviceInfos;
  3243. */
  3244. PaUtil_InitializeStreamInterface( &wdmHostApi->callbackStreamInterface, CloseStream, StartStream,
  3245. StopStream, AbortStream, IsStreamStopped, IsStreamActive,
  3246. GetStreamTime, GetStreamCpuLoad,
  3247. PaUtil_DummyRead, PaUtil_DummyWrite,
  3248. PaUtil_DummyGetReadAvailable, PaUtil_DummyGetWriteAvailable );
  3249. PaUtil_InitializeStreamInterface( &wdmHostApi->blockingStreamInterface, CloseStream, StartStream,
  3250. StopStream, AbortStream, IsStreamStopped, IsStreamActive,
  3251. GetStreamTime, PaUtil_DummyGetCpuLoad,
  3252. ReadStream, WriteStream, GetStreamReadAvailable, GetStreamWriteAvailable );
  3253. PA_LOGL_;
  3254. return result;
  3255. error:
  3256. Terminate( (PaUtilHostApiRepresentation*)wdmHostApi );
  3257. PA_LOGL_;
  3258. return result;
  3259. }
  3260. static void Terminate( struct PaUtilHostApiRepresentation *hostApi )
  3261. {
  3262. PaWinWdmHostApiRepresentation *wdmHostApi = (PaWinWdmHostApiRepresentation*)hostApi;
  3263. PA_LOGE_;
  3264. /* Do not unload the libraries */
  3265. if( DllKsUser != NULL )
  3266. {
  3267. FreeLibrary( DllKsUser );
  3268. DllKsUser = NULL;
  3269. }
  3270. if( paWinWDMKSAvRtEntryPoints.hInstance != NULL )
  3271. {
  3272. FreeLibrary( paWinWDMKSAvRtEntryPoints.hInstance );
  3273. paWinWDMKSAvRtEntryPoints.hInstance = NULL;
  3274. }
  3275. if( wdmHostApi)
  3276. {
  3277. PaWinWDMScanDeviceInfosResults* localScanResults = (PaWinWDMScanDeviceInfosResults*)PaUtil_GroupAllocateMemory(
  3278. wdmHostApi->allocations, sizeof(PaWinWDMScanDeviceInfosResults));
  3279. localScanResults->deviceInfos = hostApi->deviceInfos;
  3280. DisposeDeviceInfos(hostApi, localScanResults, hostApi->info.deviceCount);
  3281. if( wdmHostApi->allocations )
  3282. {
  3283. PaUtil_FreeAllAllocations( wdmHostApi->allocations );
  3284. PaUtil_DestroyAllocationGroup( wdmHostApi->allocations );
  3285. }
  3286. PaUtil_FreeMemory( wdmHostApi );
  3287. }
  3288. PA_LOGL_;
  3289. }
  3290. static PaError IsFormatSupported( struct PaUtilHostApiRepresentation *hostApi,
  3291. const PaStreamParameters *inputParameters,
  3292. const PaStreamParameters *outputParameters,
  3293. double sampleRate )
  3294. {
  3295. int inputChannelCount, outputChannelCount;
  3296. PaSampleFormat inputSampleFormat, outputSampleFormat;
  3297. PaWinWdmHostApiRepresentation *wdmHostApi = (PaWinWdmHostApiRepresentation*)hostApi;
  3298. PaWinWdmFilter* pFilter;
  3299. int result = paFormatIsSupported;
  3300. WAVEFORMATEXTENSIBLE wfx;
  3301. PaWinWaveFormatChannelMask channelMask;
  3302. PA_LOGE_;
  3303. if( inputParameters )
  3304. {
  3305. PaWinWdmDeviceInfo* pDeviceInfo = (PaWinWdmDeviceInfo*)wdmHostApi->inheritedHostApiRep.deviceInfos[inputParameters->device];
  3306. PaWinWdmPin* pin;
  3307. unsigned fmt;
  3308. unsigned long testFormat = 0;
  3309. unsigned validBits = 0;
  3310. inputChannelCount = inputParameters->channelCount;
  3311. inputSampleFormat = inputParameters->sampleFormat;
  3312. /* all standard sample formats are supported by the buffer adapter,
  3313. this implementation doesn't support any custom sample formats */
  3314. if( inputSampleFormat & paCustomFormat )
  3315. {
  3316. PaWinWDM_SetLastErrorInfo(paSampleFormatNotSupported, "IsFormatSupported: Custom input format not supported");
  3317. return paSampleFormatNotSupported;
  3318. }
  3319. /* unless alternate device specification is supported, reject the use of
  3320. paUseHostApiSpecificDeviceSpecification */
  3321. if( inputParameters->device == paUseHostApiSpecificDeviceSpecification )
  3322. {
  3323. PaWinWDM_SetLastErrorInfo(paInvalidDevice, "IsFormatSupported: paUseHostApiSpecificDeviceSpecification not supported");
  3324. return paInvalidDevice;
  3325. }
  3326. /* check that input device can support inputChannelCount */
  3327. if( inputChannelCount > hostApi->deviceInfos[ inputParameters->device ]->maxInputChannels )
  3328. {
  3329. PaWinWDM_SetLastErrorInfo(paInvalidChannelCount, "IsFormatSupported: Invalid input channel count");
  3330. return paInvalidChannelCount;
  3331. }
  3332. /* validate inputStreamInfo */
  3333. if( inputParameters->hostApiSpecificStreamInfo )
  3334. {
  3335. PaWinWDM_SetLastErrorInfo(paIncompatibleHostApiSpecificStreamInfo, "Host API stream info not supported");
  3336. return paIncompatibleHostApiSpecificStreamInfo; /* this implementation doesn't use custom stream info */
  3337. }
  3338. pFilter = pDeviceInfo->filter;
  3339. pin = pFilter->pins[pDeviceInfo->pin];
  3340. /* Find out the testing format */
  3341. for (fmt = paFloat32; fmt <= paUInt8; fmt <<= 1)
  3342. {
  3343. if ((fmt & pin->formats) != 0)
  3344. {
  3345. /* Found a matching format! */
  3346. testFormat = fmt;
  3347. break;
  3348. }
  3349. }
  3350. if (testFormat == 0)
  3351. {
  3352. PaWinWDM_SetLastErrorInfo(result, "IsFormatSupported(capture) failed: no testformat found!");
  3353. return paUnanticipatedHostError;
  3354. }
  3355. /* Due to special considerations, WaveRT devices with paInt24 should be tested with paInt32 and
  3356. valid bits = 24 (instead of 24 bit samples) */
  3357. if (pFilter->devInfo.streamingType == Type_kWaveRT && testFormat == paInt24)
  3358. {
  3359. PA_DEBUG(("IsFormatSupported (capture): WaveRT overriding testFormat paInt24 with paInt32 (24 valid bits)"));
  3360. testFormat = paInt32;
  3361. validBits = 24;
  3362. }
  3363. /* Check that the input format is supported */
  3364. channelMask = PaWin_DefaultChannelMask(inputChannelCount);
  3365. PaWin_InitializeWaveFormatExtensible((PaWinWaveFormat*)&wfx,
  3366. inputChannelCount,
  3367. testFormat,
  3368. PaWin_SampleFormatToLinearWaveFormatTag(testFormat),
  3369. sampleRate,
  3370. channelMask );
  3371. if (validBits != 0)
  3372. {
  3373. wfx.Samples.wValidBitsPerSample = validBits;
  3374. }
  3375. result = PinIsFormatSupported(pin, (const WAVEFORMATEX*)&wfx);
  3376. if( result != paNoError )
  3377. {
  3378. /* Try a WAVE_FORMAT_PCM instead */
  3379. PaWin_InitializeWaveFormatEx((PaWinWaveFormat*)&wfx,
  3380. inputChannelCount,
  3381. testFormat,
  3382. PaWin_SampleFormatToLinearWaveFormatTag(testFormat),
  3383. sampleRate);
  3384. if (validBits != 0)
  3385. {
  3386. wfx.Samples.wValidBitsPerSample = validBits;
  3387. }
  3388. result = PinIsFormatSupported(pin, (const WAVEFORMATEX*)&wfx);
  3389. if( result != paNoError )
  3390. {
  3391. PaWinWDM_SetLastErrorInfo(result, "IsFormatSupported(capture) failed: sr=%u,ch=%u,bits=%u", wfx.Format.nSamplesPerSec, wfx.Format.nChannels, wfx.Format.wBitsPerSample);
  3392. return result;
  3393. }
  3394. }
  3395. }
  3396. else
  3397. {
  3398. inputChannelCount = 0;
  3399. }
  3400. if( outputParameters )
  3401. {
  3402. PaWinWdmDeviceInfo* pDeviceInfo = (PaWinWdmDeviceInfo*)wdmHostApi->inheritedHostApiRep.deviceInfos[outputParameters->device];
  3403. PaWinWdmPin* pin;
  3404. unsigned fmt;
  3405. unsigned long testFormat = 0;
  3406. unsigned validBits = 0;
  3407. outputChannelCount = outputParameters->channelCount;
  3408. outputSampleFormat = outputParameters->sampleFormat;
  3409. /* all standard sample formats are supported by the buffer adapter,
  3410. this implementation doesn't support any custom sample formats */
  3411. if( outputSampleFormat & paCustomFormat )
  3412. {
  3413. PaWinWDM_SetLastErrorInfo(paSampleFormatNotSupported, "IsFormatSupported: Custom output format not supported");
  3414. return paSampleFormatNotSupported;
  3415. }
  3416. /* unless alternate device specification is supported, reject the use of
  3417. paUseHostApiSpecificDeviceSpecification */
  3418. if( outputParameters->device == paUseHostApiSpecificDeviceSpecification )
  3419. {
  3420. PaWinWDM_SetLastErrorInfo(paInvalidDevice, "IsFormatSupported: paUseHostApiSpecificDeviceSpecification not supported");
  3421. return paInvalidDevice;
  3422. }
  3423. /* check that output device can support outputChannelCount */
  3424. if( outputChannelCount > hostApi->deviceInfos[ outputParameters->device ]->maxOutputChannels )
  3425. {
  3426. PaWinWDM_SetLastErrorInfo(paInvalidChannelCount, "Invalid output channel count");
  3427. return paInvalidChannelCount;
  3428. }
  3429. /* validate outputStreamInfo */
  3430. if( outputParameters->hostApiSpecificStreamInfo )
  3431. {
  3432. PaWinWDM_SetLastErrorInfo(paIncompatibleHostApiSpecificStreamInfo, "Host API stream info not supported");
  3433. return paIncompatibleHostApiSpecificStreamInfo; /* this implementation doesn't use custom stream info */
  3434. }
  3435. pFilter = pDeviceInfo->filter;
  3436. pin = pFilter->pins[pDeviceInfo->pin];
  3437. /* Find out the testing format */
  3438. for (fmt = paFloat32; fmt <= paUInt8; fmt <<= 1)
  3439. {
  3440. if ((fmt & pin->formats) != 0)
  3441. {
  3442. /* Found a matching format! */
  3443. testFormat = fmt;
  3444. break;
  3445. }
  3446. }
  3447. if (testFormat == 0)
  3448. {
  3449. PaWinWDM_SetLastErrorInfo(result, "IsFormatSupported(render) failed: no testformat found!");
  3450. return paUnanticipatedHostError;
  3451. }
  3452. /* Due to special considerations, WaveRT devices with paInt24 should be tested with paInt32 and
  3453. valid bits = 24 (instead of 24 bit samples) */
  3454. if (pFilter->devInfo.streamingType == Type_kWaveRT && testFormat == paInt24)
  3455. {
  3456. PA_DEBUG(("IsFormatSupported (render): WaveRT overriding testFormat paInt24 with paInt32 (24 valid bits)"));
  3457. testFormat = paInt32;
  3458. validBits = 24;
  3459. }
  3460. /* Check that the output format is supported */
  3461. channelMask = PaWin_DefaultChannelMask(outputChannelCount);
  3462. PaWin_InitializeWaveFormatExtensible((PaWinWaveFormat*)&wfx,
  3463. outputChannelCount,
  3464. testFormat,
  3465. PaWin_SampleFormatToLinearWaveFormatTag(testFormat),
  3466. sampleRate,
  3467. channelMask );
  3468. if (validBits != 0)
  3469. {
  3470. wfx.Samples.wValidBitsPerSample = validBits;
  3471. }
  3472. result = PinIsFormatSupported(pin, (const WAVEFORMATEX*)&wfx);
  3473. if( result != paNoError )
  3474. {
  3475. /* Try a WAVE_FORMAT_PCM instead */
  3476. PaWin_InitializeWaveFormatEx((PaWinWaveFormat*)&wfx,
  3477. outputChannelCount,
  3478. testFormat,
  3479. PaWin_SampleFormatToLinearWaveFormatTag(testFormat),
  3480. sampleRate);
  3481. if (validBits != 0)
  3482. {
  3483. wfx.Samples.wValidBitsPerSample = validBits;
  3484. }
  3485. result = PinIsFormatSupported(pin, (const WAVEFORMATEX*)&wfx);
  3486. if( result != paNoError )
  3487. {
  3488. PaWinWDM_SetLastErrorInfo(result, "IsFormatSupported(render) failed: %u,%u,%u", wfx.Format.nSamplesPerSec, wfx.Format.nChannels, wfx.Format.wBitsPerSample);
  3489. return result;
  3490. }
  3491. }
  3492. }
  3493. else
  3494. {
  3495. outputChannelCount = 0;
  3496. }
  3497. /*
  3498. IMPLEMENT ME:
  3499. - if a full duplex stream is requested, check that the combination
  3500. of input and output parameters is supported if necessary
  3501. - check that the device supports sampleRate
  3502. Because the buffer adapter handles conversion between all standard
  3503. sample formats, the following checks are only required if paCustomFormat
  3504. is implemented, or under some other unusual conditions.
  3505. - check that input device can support inputSampleFormat, or that
  3506. we have the capability to convert from inputSampleFormat to
  3507. a native format
  3508. - check that output device can support outputSampleFormat, or that
  3509. we have the capability to convert from outputSampleFormat to
  3510. a native format
  3511. */
  3512. if((inputChannelCount == 0)&&(outputChannelCount == 0))
  3513. {
  3514. PaWinWDM_SetLastErrorInfo(paSampleFormatNotSupported, "No input or output channels defined");
  3515. result = paSampleFormatNotSupported; /* Not right error */
  3516. }
  3517. PA_LOGL_;
  3518. return result;
  3519. }
  3520. static void ResetStreamEvents(PaWinWdmStream* stream)
  3521. {
  3522. unsigned i;
  3523. ResetEvent(stream->eventAbort);
  3524. ResetEvent(stream->eventStreamStart[StreamStart_kOk]);
  3525. ResetEvent(stream->eventStreamStart[StreamStart_kFailed]);
  3526. for (i=0; i<stream->capture.noOfPackets; ++i)
  3527. {
  3528. if (stream->capture.events && stream->capture.events[i])
  3529. {
  3530. ResetEvent(stream->capture.events[i]);
  3531. }
  3532. }
  3533. for (i=0; i<stream->render.noOfPackets; ++i)
  3534. {
  3535. if (stream->render.events && stream->render.events[i])
  3536. {
  3537. ResetEvent(stream->render.events[i]);
  3538. }
  3539. }
  3540. }
  3541. static void CloseStreamEvents(PaWinWdmStream* stream)
  3542. {
  3543. unsigned i;
  3544. PaWinWdmIOInfo* ios[2] = { &stream->capture, &stream->render };
  3545. if (stream->eventAbort)
  3546. {
  3547. CloseHandle(stream->eventAbort);
  3548. stream->eventAbort = 0;
  3549. }
  3550. if (stream->eventStreamStart[StreamStart_kOk])
  3551. {
  3552. CloseHandle(stream->eventStreamStart[StreamStart_kOk]);
  3553. }
  3554. if (stream->eventStreamStart[StreamStart_kFailed])
  3555. {
  3556. CloseHandle(stream->eventStreamStart[StreamStart_kFailed]);
  3557. }
  3558. for (i = 0; i < 2; ++i)
  3559. {
  3560. unsigned j;
  3561. /* Unregister notification handles for WaveRT */
  3562. if (ios[i]->pPin && ios[i]->pPin->parentFilter->devInfo.streamingType == Type_kWaveRT &&
  3563. ios[i]->pPin->pinKsSubType == SubType_kNotification &&
  3564. ios[i]->events != 0)
  3565. {
  3566. PinUnregisterNotificationHandle(ios[i]->pPin, ios[i]->events[0]);
  3567. }
  3568. for (j=0; j < ios[i]->noOfPackets; ++j)
  3569. {
  3570. if (ios[i]->events && ios[i]->events[j])
  3571. {
  3572. CloseHandle(ios[i]->events[j]);
  3573. ios[i]->events[j] = 0;
  3574. }
  3575. }
  3576. }
  3577. }
  3578. static unsigned NextPowerOf2(unsigned val)
  3579. {
  3580. val--;
  3581. val = (val >> 1) | val;
  3582. val = (val >> 2) | val;
  3583. val = (val >> 4) | val;
  3584. val = (val >> 8) | val;
  3585. val = (val >> 16) | val;
  3586. return ++val;
  3587. }
  3588. static PaError ValidateSpecificStreamParameters(
  3589. const PaStreamParameters *streamParameters,
  3590. const PaWinWDMKSInfo *streamInfo)
  3591. {
  3592. if( streamInfo )
  3593. {
  3594. if( streamInfo->size != sizeof( PaWinWDMKSInfo )
  3595. || streamInfo->version != 1 )
  3596. {
  3597. PA_DEBUG(("Stream parameters: size or version not correct"));
  3598. return paIncompatibleHostApiSpecificStreamInfo;
  3599. }
  3600. if (streamInfo->noOfPackets != 0 &&
  3601. (streamInfo->noOfPackets < 2 || streamInfo->noOfPackets > 8))
  3602. {
  3603. PA_DEBUG(("Stream parameters: noOfPackets %u out of range [2,8]", streamInfo->noOfPackets));
  3604. return paIncompatibleHostApiSpecificStreamInfo;
  3605. }
  3606. }
  3607. return paNoError;
  3608. }
  3609. /* see pa_hostapi.h for a list of validity guarantees made about OpenStream parameters */
  3610. static PaError OpenStream( struct PaUtilHostApiRepresentation *hostApi,
  3611. PaStream** s,
  3612. const PaStreamParameters *inputParameters,
  3613. const PaStreamParameters *outputParameters,
  3614. double sampleRate,
  3615. unsigned long framesPerUserBuffer,
  3616. PaStreamFlags streamFlags,
  3617. PaStreamCallback *streamCallback,
  3618. void *userData )
  3619. {
  3620. PaError result = paNoError;
  3621. PaWinWdmHostApiRepresentation *wdmHostApi = (PaWinWdmHostApiRepresentation*)hostApi;
  3622. PaWinWdmStream *stream = 0;
  3623. /* unsigned long framesPerHostBuffer; these may not be equivalent for all implementations */
  3624. PaSampleFormat inputSampleFormat, outputSampleFormat;
  3625. PaSampleFormat hostInputSampleFormat, hostOutputSampleFormat;
  3626. int userInputChannels,userOutputChannels;
  3627. WAVEFORMATEXTENSIBLE wfx;
  3628. PA_LOGE_;
  3629. PA_DEBUG(("OpenStream:sampleRate = %f\n",sampleRate));
  3630. PA_DEBUG(("OpenStream:framesPerBuffer = %lu\n",framesPerUserBuffer));
  3631. if( inputParameters )
  3632. {
  3633. userInputChannels = inputParameters->channelCount;
  3634. inputSampleFormat = inputParameters->sampleFormat;
  3635. /* unless alternate device specification is supported, reject the use of
  3636. paUseHostApiSpecificDeviceSpecification */
  3637. if( inputParameters->device == paUseHostApiSpecificDeviceSpecification )
  3638. {
  3639. PaWinWDM_SetLastErrorInfo(paInvalidDevice, "paUseHostApiSpecificDeviceSpecification(in) not supported");
  3640. return paInvalidDevice;
  3641. }
  3642. /* check that input device can support stream->userInputChannels */
  3643. if( userInputChannels > hostApi->deviceInfos[ inputParameters->device ]->maxInputChannels )
  3644. {
  3645. PaWinWDM_SetLastErrorInfo(paInvalidChannelCount, "Invalid input channel count");
  3646. return paInvalidChannelCount;
  3647. }
  3648. /* validate inputStreamInfo */
  3649. result = ValidateSpecificStreamParameters(inputParameters, inputParameters->hostApiSpecificStreamInfo);
  3650. if(result != paNoError)
  3651. {
  3652. PaWinWDM_SetLastErrorInfo(result, "Host API stream info not supported (in)");
  3653. return result; /* this implementation doesn't use custom stream info */
  3654. }
  3655. }
  3656. else
  3657. {
  3658. userInputChannels = 0;
  3659. inputSampleFormat = hostInputSampleFormat = paInt16; /* Supress 'uninitialised var' warnings. */
  3660. }
  3661. if( outputParameters )
  3662. {
  3663. userOutputChannels = outputParameters->channelCount;
  3664. outputSampleFormat = outputParameters->sampleFormat;
  3665. /* unless alternate device specification is supported, reject the use of
  3666. paUseHostApiSpecificDeviceSpecification */
  3667. if( outputParameters->device == paUseHostApiSpecificDeviceSpecification )
  3668. {
  3669. PaWinWDM_SetLastErrorInfo(paInvalidDevice, "paUseHostApiSpecificDeviceSpecification(out) not supported");
  3670. return paInvalidDevice;
  3671. }
  3672. /* check that output device can support stream->userInputChannels */
  3673. if( userOutputChannels > hostApi->deviceInfos[ outputParameters->device ]->maxOutputChannels )
  3674. {
  3675. PaWinWDM_SetLastErrorInfo(paInvalidChannelCount, "Invalid output channel count");
  3676. return paInvalidChannelCount;
  3677. }
  3678. /* validate outputStreamInfo */
  3679. result = ValidateSpecificStreamParameters( outputParameters, outputParameters->hostApiSpecificStreamInfo );
  3680. if (result != paNoError)
  3681. {
  3682. PaWinWDM_SetLastErrorInfo(result, "Host API stream info not supported (out)");
  3683. return result; /* this implementation doesn't use custom stream info */
  3684. }
  3685. }
  3686. else
  3687. {
  3688. userOutputChannels = 0;
  3689. outputSampleFormat = hostOutputSampleFormat = paInt16; /* Supress 'uninitialized var' warnings. */
  3690. }
  3691. /* validate platform specific flags */
  3692. if( (streamFlags & paPlatformSpecificFlags) != 0 )
  3693. {
  3694. PaWinWDM_SetLastErrorInfo(paInvalidFlag, "Invalid flag supplied");
  3695. return paInvalidFlag; /* unexpected platform specific flag */
  3696. }
  3697. stream = (PaWinWdmStream*)PaUtil_AllocateMemory( sizeof(PaWinWdmStream) );
  3698. if( !stream )
  3699. {
  3700. result = paInsufficientMemory;
  3701. goto error;
  3702. }
  3703. /* Create allocation group */
  3704. stream->allocGroup = PaUtil_CreateAllocationGroup();
  3705. if( !stream->allocGroup )
  3706. {
  3707. result = paInsufficientMemory;
  3708. goto error;
  3709. }
  3710. /* Zero the stream object */
  3711. /* memset((void*)stream,0,sizeof(PaWinWdmStream)); */
  3712. if( streamCallback )
  3713. {
  3714. PaUtil_InitializeStreamRepresentation( &stream->streamRepresentation,
  3715. &wdmHostApi->callbackStreamInterface, streamCallback, userData );
  3716. }
  3717. else
  3718. {
  3719. /* PaUtil_InitializeStreamRepresentation( &stream->streamRepresentation,
  3720. &wdmHostApi->blockingStreamInterface, streamCallback, userData ); */
  3721. /* We don't support the blocking API yet */
  3722. PA_DEBUG(("Blocking API not supported yet!\n"));
  3723. PaWinWDM_SetLastErrorInfo(paUnanticipatedHostError, "Blocking API not supported yet");
  3724. result = paUnanticipatedHostError;
  3725. goto error;
  3726. }
  3727. PaUtil_InitializeCpuLoadMeasurer( &stream->cpuLoadMeasurer, sampleRate );
  3728. /* Instantiate the input pin if necessary */
  3729. if(userInputChannels > 0)
  3730. {
  3731. PaWinWdmFilter* pFilter;
  3732. PaWinWdmDeviceInfo* pDeviceInfo;
  3733. PaWinWdmPin* pPin;
  3734. unsigned validBitsPerSample = 0;
  3735. PaWinWaveFormatChannelMask channelMask = PaWin_DefaultChannelMask( userInputChannels );
  3736. result = paSampleFormatNotSupported;
  3737. pDeviceInfo = (PaWinWdmDeviceInfo*)wdmHostApi->inheritedHostApiRep.deviceInfos[inputParameters->device];
  3738. pFilter = pDeviceInfo->filter;
  3739. pPin = pFilter->pins[pDeviceInfo->pin];
  3740. stream->userInputChannels = userInputChannels;
  3741. hostInputSampleFormat = PaUtil_SelectClosestAvailableFormat( pPin->formats, inputSampleFormat );
  3742. if (hostInputSampleFormat == paSampleFormatNotSupported)
  3743. {
  3744. result = paUnanticipatedHostError;
  3745. PaWinWDM_SetLastErrorInfo(result, "PU_SCAF(%X,%X) failed (input)", pPin->formats, inputSampleFormat);
  3746. goto error;
  3747. }
  3748. else if (pFilter->devInfo.streamingType == Type_kWaveRT && hostInputSampleFormat == paInt24)
  3749. {
  3750. /* For WaveRT, we choose 32 bit format instead of paInt24, since we MIGHT need to align buffer on a
  3751. 128 byte boundary (see PinGetBuffer) */
  3752. hostInputSampleFormat = paInt32;
  3753. /* But we'll tell the driver that it's 24 bit in 32 bit container */
  3754. validBitsPerSample = 24;
  3755. }
  3756. while (hostInputSampleFormat <= paUInt8)
  3757. {
  3758. unsigned channelsToProbe = stream->userInputChannels;
  3759. /* Some or all KS devices can only handle the exact number of channels
  3760. * they specify. But PortAudio clients expect to be able to
  3761. * at least specify mono I/O on a multi-channel device
  3762. * If this is the case, then we will do the channel mapping internally
  3763. * The following loop tests this case
  3764. **/
  3765. while (1)
  3766. {
  3767. PaWin_InitializeWaveFormatExtensible((PaWinWaveFormat*)&wfx,
  3768. channelsToProbe,
  3769. hostInputSampleFormat,
  3770. PaWin_SampleFormatToLinearWaveFormatTag(hostInputSampleFormat),
  3771. sampleRate,
  3772. channelMask );
  3773. stream->capture.bytesPerFrame = wfx.Format.nBlockAlign;
  3774. if (validBitsPerSample != 0)
  3775. {
  3776. wfx.Samples.wValidBitsPerSample = validBitsPerSample;
  3777. }
  3778. stream->capture.pPin = FilterCreatePin(pFilter, pPin->pinId, (WAVEFORMATEX*)&wfx, &result);
  3779. stream->deviceInputChannels = channelsToProbe;
  3780. if( result != paNoError && result != paDeviceUnavailable )
  3781. {
  3782. /* Try a WAVE_FORMAT_PCM instead */
  3783. PaWin_InitializeWaveFormatEx((PaWinWaveFormat*)&wfx,
  3784. channelsToProbe,
  3785. hostInputSampleFormat,
  3786. PaWin_SampleFormatToLinearWaveFormatTag(hostInputSampleFormat),
  3787. sampleRate);
  3788. if (validBitsPerSample != 0)
  3789. {
  3790. wfx.Samples.wValidBitsPerSample = validBitsPerSample;
  3791. }
  3792. stream->capture.pPin = FilterCreatePin(pFilter, pPin->pinId, (const WAVEFORMATEX*)&wfx, &result);
  3793. }
  3794. if (result == paDeviceUnavailable) goto occupied;
  3795. if (result == paNoError)
  3796. {
  3797. /* We're done */
  3798. break;
  3799. }
  3800. if (channelsToProbe < (unsigned)pPin->maxChannels)
  3801. {
  3802. /* Go to next multiple of 2 */
  3803. channelsToProbe = min((((channelsToProbe>>1)+1)<<1), (unsigned)pPin->maxChannels);
  3804. continue;
  3805. }
  3806. break;
  3807. }
  3808. if (result == paNoError)
  3809. {
  3810. /* We're done */
  3811. break;
  3812. }
  3813. /* Go to next format in line with lower resolution */
  3814. hostInputSampleFormat <<= 1;
  3815. }
  3816. if(stream->capture.pPin == NULL)
  3817. {
  3818. PaWinWDM_SetLastErrorInfo(result, "Failed to create capture pin: sr=%u,ch=%u,bits=%u,align=%u",
  3819. wfx.Format.nSamplesPerSec, wfx.Format.nChannels, wfx.Format.wBitsPerSample, wfx.Format.nBlockAlign);
  3820. goto error;
  3821. }
  3822. /* Select correct mux input on MUX node of topology filter */
  3823. if (pDeviceInfo->muxPosition >= 0)
  3824. {
  3825. assert(pPin->parentFilter->topologyFilter != NULL);
  3826. result = FilterUse(pPin->parentFilter->topologyFilter);
  3827. if (result != paNoError)
  3828. {
  3829. PaWinWDM_SetLastErrorInfo(result, "Failed to open topology filter");
  3830. goto error;
  3831. }
  3832. result = WdmSetMuxNodeProperty(pPin->parentFilter->topologyFilter->handle,
  3833. pPin->inputs[pDeviceInfo->muxPosition]->muxNodeId,
  3834. pPin->inputs[pDeviceInfo->muxPosition]->muxPinId);
  3835. FilterRelease(pPin->parentFilter->topologyFilter);
  3836. if(result != paNoError)
  3837. {
  3838. PaWinWDM_SetLastErrorInfo(result, "Failed to set topology mux node");
  3839. goto error;
  3840. }
  3841. }
  3842. stream->capture.bytesPerSample = stream->capture.bytesPerFrame / stream->deviceInputChannels;
  3843. stream->capture.pPin->frameSize /= stream->capture.bytesPerFrame;
  3844. PA_DEBUG(("Capture pin frames: %d\n",stream->capture.pPin->frameSize));
  3845. }
  3846. else
  3847. {
  3848. stream->capture.pPin = NULL;
  3849. stream->capture.bytesPerFrame = 0;
  3850. }
  3851. /* Instantiate the output pin if necessary */
  3852. if(userOutputChannels > 0)
  3853. {
  3854. PaWinWdmFilter* pFilter;
  3855. PaWinWdmDeviceInfo* pDeviceInfo;
  3856. PaWinWdmPin* pPin;
  3857. unsigned validBitsPerSample = 0;
  3858. PaWinWaveFormatChannelMask channelMask = PaWin_DefaultChannelMask( userOutputChannels );
  3859. result = paSampleFormatNotSupported;
  3860. pDeviceInfo = (PaWinWdmDeviceInfo*)wdmHostApi->inheritedHostApiRep.deviceInfos[outputParameters->device];
  3861. pFilter = pDeviceInfo->filter;
  3862. pPin = pFilter->pins[pDeviceInfo->pin];
  3863. stream->userOutputChannels = userOutputChannels;
  3864. hostOutputSampleFormat = PaUtil_SelectClosestAvailableFormat( pPin->formats, outputSampleFormat );
  3865. if (hostOutputSampleFormat == paSampleFormatNotSupported)
  3866. {
  3867. result = paUnanticipatedHostError;
  3868. PaWinWDM_SetLastErrorInfo(result, "PU_SCAF(%X,%X) failed (output)", pPin->formats, hostOutputSampleFormat);
  3869. goto error;
  3870. }
  3871. else if (pFilter->devInfo.streamingType == Type_kWaveRT && hostOutputSampleFormat == paInt24)
  3872. {
  3873. /* For WaveRT, we choose 32 bit format instead of paInt24, since we MIGHT need to align buffer on a
  3874. 128 byte boundary (see PinGetBuffer) */
  3875. hostOutputSampleFormat = paInt32;
  3876. /* But we'll tell the driver that it's 24 bit in 32 bit container */
  3877. validBitsPerSample = 24;
  3878. }
  3879. while (hostOutputSampleFormat <= paUInt8)
  3880. {
  3881. unsigned channelsToProbe = stream->userOutputChannels;
  3882. /* Some or all KS devices can only handle the exact number of channels
  3883. * they specify. But PortAudio clients expect to be able to
  3884. * at least specify mono I/O on a multi-channel device
  3885. * If this is the case, then we will do the channel mapping internally
  3886. * The following loop tests this case
  3887. **/
  3888. while (1)
  3889. {
  3890. PaWin_InitializeWaveFormatExtensible((PaWinWaveFormat*)&wfx,
  3891. channelsToProbe,
  3892. hostOutputSampleFormat,
  3893. PaWin_SampleFormatToLinearWaveFormatTag(hostOutputSampleFormat),
  3894. sampleRate,
  3895. channelMask );
  3896. stream->render.bytesPerFrame = wfx.Format.nBlockAlign;
  3897. if (validBitsPerSample != 0)
  3898. {
  3899. wfx.Samples.wValidBitsPerSample = validBitsPerSample;
  3900. }
  3901. stream->render.pPin = FilterCreatePin(pFilter, pPin->pinId, (WAVEFORMATEX*)&wfx, &result);
  3902. stream->deviceOutputChannels = channelsToProbe;
  3903. if( result != paNoError && result != paDeviceUnavailable )
  3904. {
  3905. PaWin_InitializeWaveFormatEx((PaWinWaveFormat*)&wfx,
  3906. channelsToProbe,
  3907. hostOutputSampleFormat,
  3908. PaWin_SampleFormatToLinearWaveFormatTag(hostOutputSampleFormat),
  3909. sampleRate);
  3910. if (validBitsPerSample != 0)
  3911. {
  3912. wfx.Samples.wValidBitsPerSample = validBitsPerSample;
  3913. }
  3914. stream->render.pPin = FilterCreatePin(pFilter, pPin->pinId, (const WAVEFORMATEX*)&wfx, &result);
  3915. }
  3916. if (result == paDeviceUnavailable) goto occupied;
  3917. if (result == paNoError)
  3918. {
  3919. /* We're done */
  3920. break;
  3921. }
  3922. if (channelsToProbe < (unsigned)pPin->maxChannels)
  3923. {
  3924. /* Go to next multiple of 2 */
  3925. channelsToProbe = min((((channelsToProbe>>1)+1)<<1), (unsigned)pPin->maxChannels);
  3926. continue;
  3927. }
  3928. break;
  3929. };
  3930. if (result == paNoError)
  3931. {
  3932. /* We're done */
  3933. break;
  3934. }
  3935. /* Go to next format in line with lower resolution */
  3936. hostOutputSampleFormat <<= 1;
  3937. }
  3938. if(stream->render.pPin == NULL)
  3939. {
  3940. PaWinWDM_SetLastErrorInfo(result, "Failed to create render pin: sr=%u,ch=%u,bits=%u,align=%u",
  3941. wfx.Format.nSamplesPerSec, wfx.Format.nChannels, wfx.Format.wBitsPerSample, wfx.Format.nBlockAlign);
  3942. goto error;
  3943. }
  3944. stream->render.bytesPerSample = stream->render.bytesPerFrame / stream->deviceOutputChannels;
  3945. stream->render.pPin->frameSize /= stream->render.bytesPerFrame;
  3946. PA_DEBUG(("Render pin frames: %d\n",stream->render.pPin->frameSize));
  3947. }
  3948. else
  3949. {
  3950. stream->render.pPin = NULL;
  3951. stream->render.bytesPerFrame = 0;
  3952. }
  3953. /* Calculate the framesPerHostXxxxBuffer size based upon the suggested latency values */
  3954. /* Record the buffer length */
  3955. if(inputParameters)
  3956. {
  3957. /* Calculate the frames from the user's value - add a bit to round up */
  3958. stream->capture.framesPerBuffer = (unsigned long)((inputParameters->suggestedLatency*sampleRate)+0.0001);
  3959. if(stream->capture.framesPerBuffer > (unsigned long)sampleRate)
  3960. { /* Upper limit is 1 second */
  3961. stream->capture.framesPerBuffer = (unsigned long)sampleRate;
  3962. }
  3963. else if(stream->capture.framesPerBuffer < stream->capture.pPin->frameSize)
  3964. {
  3965. stream->capture.framesPerBuffer = stream->capture.pPin->frameSize;
  3966. }
  3967. PA_DEBUG(("Input frames chosen:%ld\n",stream->capture.framesPerBuffer));
  3968. /* Setup number of packets to use */
  3969. stream->capture.noOfPackets = 2;
  3970. if (inputParameters->hostApiSpecificStreamInfo)
  3971. {
  3972. PaWinWDMKSInfo* pInfo = (PaWinWDMKSInfo*)inputParameters->hostApiSpecificStreamInfo;
  3973. if (stream->capture.pPin->parentFilter->devInfo.streamingType == Type_kWaveCyclic &&
  3974. pInfo->noOfPackets != 0)
  3975. {
  3976. stream->capture.noOfPackets = pInfo->noOfPackets;
  3977. }
  3978. }
  3979. }
  3980. if(outputParameters)
  3981. {
  3982. /* Calculate the frames from the user's value - add a bit to round up */
  3983. stream->render.framesPerBuffer = (unsigned long)((outputParameters->suggestedLatency*sampleRate)+0.0001);
  3984. if(stream->render.framesPerBuffer > (unsigned long)sampleRate)
  3985. { /* Upper limit is 1 second */
  3986. stream->render.framesPerBuffer = (unsigned long)sampleRate;
  3987. }
  3988. else if(stream->render.framesPerBuffer < stream->render.pPin->frameSize)
  3989. {
  3990. stream->render.framesPerBuffer = stream->render.pPin->frameSize;
  3991. }
  3992. PA_DEBUG(("Output frames chosen:%ld\n",stream->render.framesPerBuffer));
  3993. /* Setup number of packets to use */
  3994. stream->render.noOfPackets = 2;
  3995. if (outputParameters->hostApiSpecificStreamInfo)
  3996. {
  3997. PaWinWDMKSInfo* pInfo = (PaWinWDMKSInfo*)outputParameters->hostApiSpecificStreamInfo;
  3998. if (stream->render.pPin->parentFilter->devInfo.streamingType == Type_kWaveCyclic &&
  3999. pInfo->noOfPackets != 0)
  4000. {
  4001. stream->render.noOfPackets = pInfo->noOfPackets;
  4002. }
  4003. }
  4004. }
  4005. /* Host buffer size is bound to the largest of the input and output frame sizes */
  4006. result = PaUtil_InitializeBufferProcessor( &stream->bufferProcessor,
  4007. stream->userInputChannels, inputSampleFormat, hostInputSampleFormat,
  4008. stream->userOutputChannels, outputSampleFormat, hostOutputSampleFormat,
  4009. sampleRate, streamFlags, framesPerUserBuffer,
  4010. max(stream->capture.framesPerBuffer, stream->render.framesPerBuffer),
  4011. paUtilBoundedHostBufferSize,
  4012. streamCallback, userData );
  4013. if( result != paNoError )
  4014. {
  4015. PaWinWDM_SetLastErrorInfo(result, "PaUtil_InitializeBufferProcessor failed: ich=%u, isf=%u, hisf=%u, och=%u, osf=%u, hosf=%u, sr=%lf, flags=0x%X, fpub=%u, fphb=%u",
  4016. stream->userInputChannels, inputSampleFormat, hostInputSampleFormat,
  4017. stream->userOutputChannels, outputSampleFormat, hostOutputSampleFormat,
  4018. sampleRate, streamFlags, framesPerUserBuffer,
  4019. max(stream->capture.framesPerBuffer, stream->render.framesPerBuffer));
  4020. goto error;
  4021. }
  4022. /* Allocate/get all the buffers for host I/O */
  4023. if (stream->userInputChannels > 0)
  4024. {
  4025. stream->streamRepresentation.streamInfo.inputLatency = stream->capture.framesPerBuffer / sampleRate;
  4026. switch (stream->capture.pPin->parentFilter->devInfo.streamingType)
  4027. {
  4028. case Type_kWaveCyclic:
  4029. {
  4030. unsigned size = stream->capture.noOfPackets * stream->capture.framesPerBuffer * stream->capture.bytesPerFrame;
  4031. /* Allocate input host buffer */
  4032. stream->capture.hostBuffer = (char*)PaUtil_GroupAllocateMemory(stream->allocGroup, size);
  4033. PA_DEBUG(("Input buffer allocated (size = %u)\n", size));
  4034. if( !stream->capture.hostBuffer )
  4035. {
  4036. PA_DEBUG(("Cannot allocate host input buffer!\n"));
  4037. PaWinWDM_SetLastErrorInfo(paInsufficientMemory, "Failed to allocate input buffer");
  4038. result = paInsufficientMemory;
  4039. goto error;
  4040. }
  4041. stream->capture.hostBufferSize = size;
  4042. PA_DEBUG(("Input buffer start = %p (size=%u)\n",stream->capture.hostBuffer, stream->capture.hostBufferSize));
  4043. stream->capture.pPin->fnEventHandler = PaPinCaptureEventHandler_WaveCyclic;
  4044. stream->capture.pPin->fnSubmitHandler = PaPinCaptureSubmitHandler_WaveCyclic;
  4045. }
  4046. break;
  4047. case Type_kWaveRT:
  4048. {
  4049. const DWORD dwTotalSize = 2 * stream->capture.framesPerBuffer * stream->capture.bytesPerFrame;
  4050. DWORD dwRequestedSize = dwTotalSize;
  4051. BOOL bCallMemoryBarrier = FALSE;
  4052. ULONG hwFifoLatency = 0;
  4053. ULONG dummy;
  4054. result = PinGetBuffer(stream->capture.pPin, (void**)&stream->capture.hostBuffer, &dwRequestedSize, &bCallMemoryBarrier);
  4055. if (!result)
  4056. {
  4057. PA_DEBUG(("Input buffer start = %p, size = %u\n", stream->capture.hostBuffer, dwRequestedSize));
  4058. if (dwRequestedSize != dwTotalSize)
  4059. {
  4060. PA_DEBUG(("Buffer length changed by driver from %u to %u !\n", dwTotalSize, dwRequestedSize));
  4061. /* Recalculate to what the driver has given us */
  4062. stream->capture.framesPerBuffer = dwRequestedSize / (2 * stream->capture.bytesPerFrame);
  4063. }
  4064. stream->capture.hostBufferSize = dwRequestedSize;
  4065. if (stream->capture.pPin->pinKsSubType == SubType_kPolled)
  4066. {
  4067. stream->capture.pPin->fnEventHandler = PaPinCaptureEventHandler_WaveRTPolled;
  4068. stream->capture.pPin->fnSubmitHandler = PaPinCaptureSubmitHandler_WaveRTPolled;
  4069. }
  4070. else
  4071. {
  4072. stream->capture.pPin->fnEventHandler = PaPinCaptureEventHandler_WaveRTEvent;
  4073. stream->capture.pPin->fnSubmitHandler = PaPinCaptureSubmitHandler_WaveRTEvent;
  4074. }
  4075. stream->capture.pPin->fnMemBarrier = bCallMemoryBarrier ? MemoryBarrierRead : MemoryBarrierDummy;
  4076. }
  4077. else
  4078. {
  4079. PA_DEBUG(("Failed to get input buffer (WaveRT)\n"));
  4080. PaWinWDM_SetLastErrorInfo(paUnanticipatedHostError, "Failed to get input buffer (WaveRT)");
  4081. result = paUnanticipatedHostError;
  4082. goto error;
  4083. }
  4084. /* Get latency */
  4085. result = PinGetHwLatency(stream->capture.pPin, &hwFifoLatency, &dummy, &dummy);
  4086. if (result == paNoError)
  4087. {
  4088. stream->capture.pPin->hwLatency = hwFifoLatency;
  4089. /* Add HW latency into total input latency */
  4090. stream->streamRepresentation.streamInfo.inputLatency += ((hwFifoLatency / stream->capture.bytesPerFrame) / sampleRate);
  4091. }
  4092. else
  4093. {
  4094. PA_DEBUG(("Failed to get size of FIFO hardware buffer (is set to zero)\n"));
  4095. stream->capture.pPin->hwLatency = 0;
  4096. }
  4097. }
  4098. break;
  4099. default:
  4100. /* Undefined wave type!! */
  4101. assert(0);
  4102. result = paInternalError;
  4103. PaWinWDM_SetLastErrorInfo(result, "Wave type %u ??", stream->capture.pPin->parentFilter->devInfo.streamingType);
  4104. goto error;
  4105. }
  4106. }
  4107. else
  4108. {
  4109. stream->capture.hostBuffer = 0;
  4110. }
  4111. if (stream->userOutputChannels > 0)
  4112. {
  4113. stream->streamRepresentation.streamInfo.outputLatency = stream->render.framesPerBuffer / sampleRate;
  4114. switch (stream->render.pPin->parentFilter->devInfo.streamingType)
  4115. {
  4116. case Type_kWaveCyclic:
  4117. {
  4118. unsigned size = stream->render.noOfPackets * stream->render.framesPerBuffer * stream->render.bytesPerFrame;
  4119. /* Allocate output device buffer */
  4120. stream->render.hostBuffer = (char*)PaUtil_GroupAllocateMemory(stream->allocGroup, size);
  4121. PA_DEBUG(("Output buffer allocated (size = %u)\n", size));
  4122. if( !stream->render.hostBuffer )
  4123. {
  4124. PA_DEBUG(("Cannot allocate host output buffer!\n"));
  4125. PaWinWDM_SetLastErrorInfo(paInsufficientMemory, "Failed to allocate output buffer");
  4126. result = paInsufficientMemory;
  4127. goto error;
  4128. }
  4129. stream->render.hostBufferSize = size;
  4130. PA_DEBUG(("Output buffer start = %p (size=%u)\n",stream->render.hostBuffer, stream->render.hostBufferSize));
  4131. stream->render.pPin->fnEventHandler = PaPinRenderEventHandler_WaveCyclic;
  4132. stream->render.pPin->fnSubmitHandler = PaPinRenderSubmitHandler_WaveCyclic;
  4133. }
  4134. break;
  4135. case Type_kWaveRT:
  4136. {
  4137. const DWORD dwTotalSize = 2 * stream->render.framesPerBuffer * stream->render.bytesPerFrame;
  4138. DWORD dwRequestedSize = dwTotalSize;
  4139. BOOL bCallMemoryBarrier = FALSE;
  4140. ULONG hwFifoLatency = 0;
  4141. ULONG dummy;
  4142. result = PinGetBuffer(stream->render.pPin, (void**)&stream->render.hostBuffer, &dwRequestedSize, &bCallMemoryBarrier);
  4143. if (!result)
  4144. {
  4145. PA_DEBUG(("Output buffer start = %p, size = %u, membarrier = %u\n", stream->render.hostBuffer, dwRequestedSize, bCallMemoryBarrier));
  4146. if (dwRequestedSize != dwTotalSize)
  4147. {
  4148. PA_DEBUG(("Buffer length changed by driver from %u to %u !\n", dwTotalSize, dwRequestedSize));
  4149. /* Recalculate to what the driver has given us */
  4150. stream->render.framesPerBuffer = dwRequestedSize / (2 * stream->render.bytesPerFrame);
  4151. }
  4152. stream->render.hostBufferSize = dwRequestedSize;
  4153. if (stream->render.pPin->pinKsSubType == SubType_kPolled)
  4154. {
  4155. stream->render.pPin->fnEventHandler = PaPinRenderEventHandler_WaveRTPolled;
  4156. stream->render.pPin->fnSubmitHandler = PaPinRenderSubmitHandler_WaveRTPolled;
  4157. }
  4158. else
  4159. {
  4160. stream->render.pPin->fnEventHandler = PaPinRenderEventHandler_WaveRTEvent;
  4161. stream->render.pPin->fnSubmitHandler = PaPinRenderSubmitHandler_WaveRTEvent;
  4162. }
  4163. stream->render.pPin->fnMemBarrier = bCallMemoryBarrier ? MemoryBarrierWrite : MemoryBarrierDummy;
  4164. }
  4165. else
  4166. {
  4167. PA_DEBUG(("Failed to get output buffer (with notification)\n"));
  4168. PaWinWDM_SetLastErrorInfo(paUnanticipatedHostError, "Failed to get output buffer (with notification)");
  4169. result = paUnanticipatedHostError;
  4170. goto error;
  4171. }
  4172. /* Get latency */
  4173. result = PinGetHwLatency(stream->render.pPin, &hwFifoLatency, &dummy, &dummy);
  4174. if (result == paNoError)
  4175. {
  4176. stream->render.pPin->hwLatency = hwFifoLatency;
  4177. /* Add HW latency into total output latency */
  4178. stream->streamRepresentation.streamInfo.outputLatency += ((hwFifoLatency / stream->render.bytesPerFrame) / sampleRate);
  4179. }
  4180. else
  4181. {
  4182. PA_DEBUG(("Failed to get size of FIFO hardware buffer (is set to zero)\n"));
  4183. stream->render.pPin->hwLatency = 0;
  4184. }
  4185. }
  4186. break;
  4187. default:
  4188. /* Undefined wave type!! */
  4189. assert(0);
  4190. result = paInternalError;
  4191. PaWinWDM_SetLastErrorInfo(result, "Wave type %u ??", stream->capture.pPin->parentFilter->devInfo.streamingType);
  4192. goto error;
  4193. }
  4194. }
  4195. else
  4196. {
  4197. stream->render.hostBuffer = 0;
  4198. }
  4199. stream->streamRepresentation.streamInfo.sampleRate = sampleRate;
  4200. PA_DEBUG(("BytesPerInputFrame = %d\n",stream->capture.bytesPerFrame));
  4201. PA_DEBUG(("BytesPerOutputFrame = %d\n",stream->render.bytesPerFrame));
  4202. /* memset(stream->hostBuffer,0,size); */
  4203. /* Abort */
  4204. stream->eventAbort = CreateEvent(NULL, TRUE, FALSE, NULL);
  4205. if (stream->eventAbort == 0)
  4206. {
  4207. result = paInsufficientMemory;
  4208. goto error;
  4209. }
  4210. stream->eventStreamStart[0] = CreateEvent(NULL, TRUE, FALSE, NULL);
  4211. if (stream->eventStreamStart[0] == 0)
  4212. {
  4213. result = paInsufficientMemory;
  4214. goto error;
  4215. }
  4216. stream->eventStreamStart[1] = CreateEvent(NULL, TRUE, FALSE, NULL);
  4217. if (stream->eventStreamStart[1] == 0)
  4218. {
  4219. result = paInsufficientMemory;
  4220. goto error;
  4221. }
  4222. if(stream->userInputChannels > 0)
  4223. {
  4224. const unsigned bufferSizeInBytes = stream->capture.framesPerBuffer * stream->capture.bytesPerFrame;
  4225. const unsigned ringBufferFrameSize = NextPowerOf2( 1024 + 2 * max(stream->capture.framesPerBuffer, stream->render.framesPerBuffer) );
  4226. stream->capture.events = (HANDLE*)PaUtil_GroupAllocateMemory(stream->allocGroup, stream->capture.noOfPackets * sizeof(HANDLE));
  4227. if (stream->capture.events == NULL)
  4228. {
  4229. result = paInsufficientMemory;
  4230. goto error;
  4231. }
  4232. stream->capture.packets = (DATAPACKET*)PaUtil_GroupAllocateMemory(stream->allocGroup, stream->capture.noOfPackets * sizeof(DATAPACKET));
  4233. if (stream->capture.packets == NULL)
  4234. {
  4235. result = paInsufficientMemory;
  4236. goto error;
  4237. }
  4238. switch(stream->capture.pPin->parentFilter->devInfo.streamingType)
  4239. {
  4240. case Type_kWaveCyclic:
  4241. {
  4242. /* WaveCyclic case */
  4243. unsigned i;
  4244. for (i = 0; i < stream->capture.noOfPackets; ++i)
  4245. {
  4246. /* Set up the packets */
  4247. DATAPACKET *p = stream->capture.packets + i;
  4248. /* Record event */
  4249. stream->capture.events[i] = CreateEvent(NULL, TRUE, FALSE, NULL);
  4250. p->Signal.hEvent = stream->capture.events[i];
  4251. p->Header.Data = stream->capture.hostBuffer + (i*bufferSizeInBytes);
  4252. p->Header.FrameExtent = bufferSizeInBytes;
  4253. p->Header.DataUsed = 0;
  4254. p->Header.Size = sizeof(p->Header);
  4255. p->Header.PresentationTime.Numerator = 1;
  4256. p->Header.PresentationTime.Denominator = 1;
  4257. }
  4258. }
  4259. break;
  4260. case Type_kWaveRT:
  4261. {
  4262. /* Set up the "packets" */
  4263. DATAPACKET *p = stream->capture.packets + 0;
  4264. /* Record event: WaveRT has a single event for 2 notification per buffer */
  4265. stream->capture.events[0] = CreateEvent(NULL, FALSE, FALSE, NULL);
  4266. p->Header.Data = stream->capture.hostBuffer;
  4267. p->Header.FrameExtent = bufferSizeInBytes;
  4268. p->Header.DataUsed = 0;
  4269. p->Header.Size = sizeof(p->Header);
  4270. p->Header.PresentationTime.Numerator = 1;
  4271. p->Header.PresentationTime.Denominator = 1;
  4272. ++p;
  4273. p->Header.Data = stream->capture.hostBuffer + bufferSizeInBytes;
  4274. p->Header.FrameExtent = bufferSizeInBytes;
  4275. p->Header.DataUsed = 0;
  4276. p->Header.Size = sizeof(p->Header);
  4277. p->Header.PresentationTime.Numerator = 1;
  4278. p->Header.PresentationTime.Denominator = 1;
  4279. if (stream->capture.pPin->pinKsSubType == SubType_kNotification)
  4280. {
  4281. result = PinRegisterNotificationHandle(stream->capture.pPin, stream->capture.events[0]);
  4282. if (result != paNoError)
  4283. {
  4284. PA_DEBUG(("Failed to register capture notification handle\n"));
  4285. PaWinWDM_SetLastErrorInfo(paUnanticipatedHostError, "Failed to register capture notification handle");
  4286. result = paUnanticipatedHostError;
  4287. goto error;
  4288. }
  4289. }
  4290. result = PinRegisterPositionRegister(stream->capture.pPin);
  4291. if (result != paNoError)
  4292. {
  4293. unsigned long pos = 0xdeadc0de;
  4294. PA_DEBUG(("Failed to register capture position register, using PinGetAudioPositionViaIOCTL\n"));
  4295. stream->capture.pPin->fnAudioPosition = PinGetAudioPositionViaIOCTL;
  4296. /* Test position function */
  4297. result = (stream->capture.pPin->fnAudioPosition)(stream->capture.pPin, &pos);
  4298. if (result != paNoError || pos != 0x0)
  4299. {
  4300. PA_DEBUG(("Failed to read capture position register (IOCTL)\n"));
  4301. PaWinWDM_SetLastErrorInfo(paUnanticipatedHostError, "Failed to read capture position register (IOCTL)");
  4302. result = paUnanticipatedHostError;
  4303. goto error;
  4304. }
  4305. }
  4306. else
  4307. {
  4308. stream->capture.pPin->fnAudioPosition = PinGetAudioPositionDirect;
  4309. }
  4310. }
  4311. break;
  4312. default:
  4313. /* Undefined wave type!! */
  4314. assert(0);
  4315. result = paInternalError;
  4316. PaWinWDM_SetLastErrorInfo(result, "Wave type %u ??", stream->capture.pPin->parentFilter->devInfo.streamingType);
  4317. goto error;
  4318. }
  4319. /* Setup the input ring buffer here */
  4320. stream->ringBufferData = (char*)PaUtil_GroupAllocateMemory(stream->allocGroup, ringBufferFrameSize * stream->capture.bytesPerFrame);
  4321. if (stream->ringBufferData == NULL)
  4322. {
  4323. result = paInsufficientMemory;
  4324. goto error;
  4325. }
  4326. PaUtil_InitializeRingBuffer(&stream->ringBuffer, stream->capture.bytesPerFrame, ringBufferFrameSize, stream->ringBufferData);
  4327. }
  4328. if(stream->userOutputChannels > 0)
  4329. {
  4330. const unsigned bufferSizeInBytes = stream->render.framesPerBuffer * stream->render.bytesPerFrame;
  4331. stream->render.events = (HANDLE*)PaUtil_GroupAllocateMemory(stream->allocGroup, stream->render.noOfPackets * sizeof(HANDLE));
  4332. if (stream->render.events == NULL)
  4333. {
  4334. result = paInsufficientMemory;
  4335. goto error;
  4336. }
  4337. stream->render.packets = (DATAPACKET*)PaUtil_GroupAllocateMemory(stream->allocGroup, stream->render.noOfPackets * sizeof(DATAPACKET));
  4338. if (stream->render.packets == NULL)
  4339. {
  4340. result = paInsufficientMemory;
  4341. goto error;
  4342. }
  4343. switch(stream->render.pPin->parentFilter->devInfo.streamingType)
  4344. {
  4345. case Type_kWaveCyclic:
  4346. {
  4347. /* WaveCyclic case */
  4348. unsigned i;
  4349. for (i = 0; i < stream->render.noOfPackets; ++i)
  4350. {
  4351. /* Set up the packets */
  4352. DATAPACKET *p = stream->render.packets + i;
  4353. /* Playback event */
  4354. stream->render.events[i] = CreateEvent(NULL, TRUE, FALSE, NULL);
  4355. /* In this case, we just use the packets as ptr to the device buffer */
  4356. p->Signal.hEvent = stream->render.events[i];
  4357. p->Header.Data = stream->render.hostBuffer + (i*bufferSizeInBytes);
  4358. p->Header.FrameExtent = bufferSizeInBytes;
  4359. p->Header.DataUsed = bufferSizeInBytes;
  4360. p->Header.Size = sizeof(p->Header);
  4361. p->Header.PresentationTime.Numerator = 1;
  4362. p->Header.PresentationTime.Denominator = 1;
  4363. }
  4364. }
  4365. break;
  4366. case Type_kWaveRT:
  4367. {
  4368. /* WaveRT case */
  4369. /* Set up the "packets" */
  4370. DATAPACKET *p = stream->render.packets;
  4371. /* The only playback event */
  4372. stream->render.events[0] = CreateEvent(NULL, FALSE, FALSE, NULL);
  4373. /* In this case, we just use the packets as ptr to the device buffer */
  4374. p->Header.Data = stream->render.hostBuffer;
  4375. p->Header.FrameExtent = stream->render.framesPerBuffer*stream->render.bytesPerFrame;
  4376. p->Header.DataUsed = stream->render.framesPerBuffer*stream->render.bytesPerFrame;
  4377. p->Header.Size = sizeof(p->Header);
  4378. p->Header.PresentationTime.Numerator = 1;
  4379. p->Header.PresentationTime.Denominator = 1;
  4380. ++p;
  4381. p->Header.Data = stream->render.hostBuffer + stream->render.framesPerBuffer*stream->render.bytesPerFrame;
  4382. p->Header.FrameExtent = stream->render.framesPerBuffer*stream->render.bytesPerFrame;
  4383. p->Header.DataUsed = stream->render.framesPerBuffer*stream->render.bytesPerFrame;
  4384. p->Header.Size = sizeof(p->Header);
  4385. p->Header.PresentationTime.Numerator = 1;
  4386. p->Header.PresentationTime.Denominator = 1;
  4387. if (stream->render.pPin->pinKsSubType == SubType_kNotification)
  4388. {
  4389. result = PinRegisterNotificationHandle(stream->render.pPin, stream->render.events[0]);
  4390. if (result != paNoError)
  4391. {
  4392. PA_DEBUG(("Failed to register rendering notification handle\n"));
  4393. PaWinWDM_SetLastErrorInfo(paUnanticipatedHostError, "Failed to register rendering notification handle");
  4394. result = paUnanticipatedHostError;
  4395. goto error;
  4396. }
  4397. }
  4398. result = PinRegisterPositionRegister(stream->render.pPin);
  4399. if (result != paNoError)
  4400. {
  4401. unsigned long pos = 0xdeadc0de;
  4402. PA_DEBUG(("Failed to register rendering position register, using PinGetAudioPositionViaIOCTL\n"));
  4403. stream->render.pPin->fnAudioPosition = PinGetAudioPositionViaIOCTL;
  4404. /* Test position function */
  4405. result = (stream->render.pPin->fnAudioPosition)(stream->render.pPin, &pos);
  4406. if (result != paNoError || pos != 0x0)
  4407. {
  4408. PA_DEBUG(("Failed to read render position register (IOCTL)\n"));
  4409. PaWinWDM_SetLastErrorInfo(paUnanticipatedHostError, "Failed to read render position register (IOCTL)");
  4410. result = paUnanticipatedHostError;
  4411. goto error;
  4412. }
  4413. }
  4414. else
  4415. {
  4416. stream->render.pPin->fnAudioPosition = PinGetAudioPositionDirect;
  4417. }
  4418. }
  4419. break;
  4420. default:
  4421. /* Undefined wave type!! */
  4422. assert(0);
  4423. result = paInternalError;
  4424. PaWinWDM_SetLastErrorInfo(result, "Wave type %u ??", stream->capture.pPin->parentFilter->devInfo.streamingType);
  4425. goto error;
  4426. }
  4427. }
  4428. stream->streamStarted = 0;
  4429. stream->streamActive = 0;
  4430. stream->streamStop = 0;
  4431. stream->streamAbort = 0;
  4432. stream->streamFlags = streamFlags;
  4433. stream->oldProcessPriority = REALTIME_PRIORITY_CLASS;
  4434. /* Increase ref count on filters in use, so that a CommitDeviceInfos won't delete them */
  4435. if (stream->capture.pPin != 0)
  4436. {
  4437. FilterAddRef(stream->capture.pPin->parentFilter);
  4438. }
  4439. if (stream->render.pPin != 0)
  4440. {
  4441. FilterAddRef(stream->render.pPin->parentFilter);
  4442. }
  4443. /* Ok, now update our host API specific stream info */
  4444. if (stream->userInputChannels)
  4445. {
  4446. PaWinWdmDeviceInfo *pDeviceInfo = (PaWinWdmDeviceInfo*)wdmHostApi->inheritedHostApiRep.deviceInfos[inputParameters->device];
  4447. stream->hostApiStreamInfo.input.device = Pa_HostApiDeviceIndexToDeviceIndex(Pa_HostApiTypeIdToHostApiIndex(paWDMKS), inputParameters->device);
  4448. stream->hostApiStreamInfo.input.channels = stream->deviceInputChannels;
  4449. stream->hostApiStreamInfo.input.muxNodeId = -1;
  4450. if (stream->capture.pPin->inputs)
  4451. {
  4452. stream->hostApiStreamInfo.input.muxNodeId = stream->capture.pPin->inputs[pDeviceInfo->muxPosition]->muxNodeId;
  4453. }
  4454. stream->hostApiStreamInfo.input.endpointPinId = pDeviceInfo->endpointPinId;
  4455. stream->hostApiStreamInfo.input.framesPerHostBuffer = stream->capture.framesPerBuffer;
  4456. stream->hostApiStreamInfo.input.streamingSubType = stream->capture.pPin->pinKsSubType;
  4457. }
  4458. else
  4459. {
  4460. stream->hostApiStreamInfo.input.device = paNoDevice;
  4461. }
  4462. if (stream->userOutputChannels)
  4463. {
  4464. stream->hostApiStreamInfo.output.device = Pa_HostApiDeviceIndexToDeviceIndex(Pa_HostApiTypeIdToHostApiIndex(paWDMKS), outputParameters->device);
  4465. stream->hostApiStreamInfo.output.channels = stream->deviceOutputChannels;
  4466. stream->hostApiStreamInfo.output.framesPerHostBuffer = stream->render.framesPerBuffer;
  4467. stream->hostApiStreamInfo.output.endpointPinId = stream->render.pPin->endpointPinId;
  4468. stream->hostApiStreamInfo.output.streamingSubType = stream->render.pPin->pinKsSubType;
  4469. }
  4470. else
  4471. {
  4472. stream->hostApiStreamInfo.output.device = paNoDevice;
  4473. }
  4474. /*stream->streamRepresentation.streamInfo.hostApiTypeId = paWDMKS;
  4475. stream->streamRepresentation.streamInfo.hostApiSpecificStreamInfo = &stream->hostApiStreamInfo;*/
  4476. stream->streamRepresentation.streamInfo.structVersion = 2;
  4477. *s = (PaStream*)stream;
  4478. PA_LOGL_;
  4479. return result;
  4480. occupied:
  4481. /* Ok, someone else is hogging the pin, bail out */
  4482. assert (result == paDeviceUnavailable);
  4483. PaWinWDM_SetLastErrorInfo(result, "Device is occupied");
  4484. error:
  4485. PaUtil_TerminateBufferProcessor( &stream->bufferProcessor );
  4486. CloseStreamEvents(stream);
  4487. if (stream->allocGroup)
  4488. {
  4489. PaUtil_FreeAllAllocations(stream->allocGroup);
  4490. PaUtil_DestroyAllocationGroup(stream->allocGroup);
  4491. stream->allocGroup = 0;
  4492. }
  4493. if(stream->render.pPin)
  4494. PinClose(stream->render.pPin);
  4495. if(stream->capture.pPin)
  4496. PinClose(stream->capture.pPin);
  4497. PaUtil_FreeMemory( stream );
  4498. PA_LOGL_;
  4499. return result;
  4500. }
  4501. /*
  4502. When CloseStream() is called, the multi-api layer ensures that
  4503. the stream has already been stopped or aborted.
  4504. */
  4505. static PaError CloseStream( PaStream* s )
  4506. {
  4507. PaError result = paNoError;
  4508. PaWinWdmStream *stream = (PaWinWdmStream*)s;
  4509. PA_LOGE_;
  4510. assert(!stream->streamStarted);
  4511. assert(!stream->streamActive);
  4512. PaUtil_TerminateBufferProcessor( &stream->bufferProcessor );
  4513. PaUtil_TerminateStreamRepresentation( &stream->streamRepresentation );
  4514. CloseStreamEvents(stream);
  4515. if (stream->allocGroup)
  4516. {
  4517. PaUtil_FreeAllAllocations(stream->allocGroup);
  4518. PaUtil_DestroyAllocationGroup(stream->allocGroup);
  4519. stream->allocGroup = 0;
  4520. }
  4521. if(stream->render.pPin)
  4522. {
  4523. PinClose(stream->render.pPin);
  4524. }
  4525. if(stream->capture.pPin)
  4526. {
  4527. PinClose(stream->capture.pPin);
  4528. }
  4529. if (stream->render.pPin)
  4530. {
  4531. FilterFree(stream->render.pPin->parentFilter);
  4532. }
  4533. if (stream->capture.pPin)
  4534. {
  4535. FilterFree(stream->capture.pPin->parentFilter);
  4536. }
  4537. PaUtil_FreeMemory( stream );
  4538. PA_LOGL_;
  4539. return result;
  4540. }
  4541. /*
  4542. Write the supplied packet to the pin
  4543. Asynchronous
  4544. Should return paNoError on success
  4545. */
  4546. static PaError PinWrite(HANDLE h, DATAPACKET* p)
  4547. {
  4548. PaError result = paNoError;
  4549. unsigned long cbReturned = 0;
  4550. BOOL fRes = DeviceIoControl(h,
  4551. IOCTL_KS_WRITE_STREAM,
  4552. NULL,
  4553. 0,
  4554. &p->Header,
  4555. p->Header.Size,
  4556. &cbReturned,
  4557. &p->Signal);
  4558. if (!fRes)
  4559. {
  4560. unsigned long error = GetLastError();
  4561. if (error != ERROR_IO_PENDING)
  4562. {
  4563. result = paInternalError;
  4564. }
  4565. }
  4566. return result;
  4567. }
  4568. /*
  4569. Read to the supplied packet from the pin
  4570. Asynchronous
  4571. Should return paNoError on success
  4572. */
  4573. static PaError PinRead(HANDLE h, DATAPACKET* p)
  4574. {
  4575. PaError result = paNoError;
  4576. unsigned long cbReturned = 0;
  4577. BOOL fRes = DeviceIoControl(h,
  4578. IOCTL_KS_READ_STREAM,
  4579. NULL,
  4580. 0,
  4581. &p->Header,
  4582. p->Header.Size,
  4583. &cbReturned,
  4584. &p->Signal);
  4585. if (!fRes)
  4586. {
  4587. unsigned long error = GetLastError();
  4588. if (error != ERROR_IO_PENDING)
  4589. {
  4590. result = paInternalError;
  4591. }
  4592. }
  4593. return result;
  4594. }
  4595. /*
  4596. Copy the first interleaved channel of 16 bit data to the other channels
  4597. */
  4598. static void DuplicateFirstChannelInt16(void* buffer, int channels, int samples)
  4599. {
  4600. unsigned short* data = (unsigned short*)buffer;
  4601. int channel;
  4602. unsigned short sourceSample;
  4603. while( samples-- )
  4604. {
  4605. sourceSample = *data++;
  4606. channel = channels-1;
  4607. while( channel-- )
  4608. {
  4609. *data++ = sourceSample;
  4610. }
  4611. }
  4612. }
  4613. /*
  4614. Copy the first interleaved channel of 24 bit data to the other channels
  4615. */
  4616. static void DuplicateFirstChannelInt24(void* buffer, int channels, int samples)
  4617. {
  4618. unsigned char* data = (unsigned char*)buffer;
  4619. int channel;
  4620. unsigned char sourceSample[3];
  4621. while( samples-- )
  4622. {
  4623. sourceSample[0] = data[0];
  4624. sourceSample[1] = data[1];
  4625. sourceSample[2] = data[2];
  4626. data += 3;
  4627. channel = channels-1;
  4628. while( channel-- )
  4629. {
  4630. data[0] = sourceSample[0];
  4631. data[1] = sourceSample[1];
  4632. data[2] = sourceSample[2];
  4633. data += 3;
  4634. }
  4635. }
  4636. }
  4637. /*
  4638. Copy the first interleaved channel of 32 bit data to the other channels
  4639. */
  4640. static void DuplicateFirstChannelInt32(void* buffer, int channels, int samples)
  4641. {
  4642. unsigned long* data = (unsigned long*)buffer;
  4643. int channel;
  4644. unsigned long sourceSample;
  4645. while( samples-- )
  4646. {
  4647. sourceSample = *data++;
  4648. channel = channels-1;
  4649. while( channel-- )
  4650. {
  4651. *data++ = sourceSample;
  4652. }
  4653. }
  4654. }
  4655. /*
  4656. Increase the priority of the calling thread to RT
  4657. */
  4658. static HANDLE BumpThreadPriority()
  4659. {
  4660. HANDLE hThread = GetCurrentThread();
  4661. DWORD dwTask = 0;
  4662. HANDLE hAVRT = NULL;
  4663. /* If we have access to AVRT.DLL (Vista and later), use it */
  4664. if (paWinWDMKSAvRtEntryPoints.AvSetMmThreadCharacteristics != NULL)
  4665. {
  4666. hAVRT = paWinWDMKSAvRtEntryPoints.AvSetMmThreadCharacteristics("Pro Audio", &dwTask);
  4667. if (hAVRT != NULL && hAVRT != INVALID_HANDLE_VALUE)
  4668. {
  4669. BOOL bret = paWinWDMKSAvRtEntryPoints.AvSetMmThreadPriority(hAVRT, PA_AVRT_PRIORITY_CRITICAL);
  4670. if (!bret)
  4671. {
  4672. PA_DEBUG(("Set mm thread prio to critical failed!\n"));
  4673. }
  4674. else
  4675. {
  4676. return hAVRT;
  4677. }
  4678. }
  4679. else
  4680. {
  4681. PA_DEBUG(("Set mm thread characteristic to 'Pro Audio' failed, reverting to SetThreadPriority\n"));
  4682. }
  4683. }
  4684. /* For XP and earlier, or if AvSetMmThreadCharacteristics fails (MMCSS disabled ?) */
  4685. if (timeBeginPeriod(1) != TIMERR_NOERROR) {
  4686. PA_DEBUG(("timeBeginPeriod(1) failed!\n"));
  4687. }
  4688. if (!SetThreadPriority(hThread, THREAD_PRIORITY_TIME_CRITICAL)) {
  4689. PA_DEBUG(("SetThreadPriority failed!\n"));
  4690. }
  4691. return hAVRT;
  4692. }
  4693. /*
  4694. Decrease the priority of the calling thread to normal
  4695. */
  4696. static void DropThreadPriority(HANDLE hAVRT)
  4697. {
  4698. HANDLE hThread = GetCurrentThread();
  4699. if (hAVRT != NULL)
  4700. {
  4701. paWinWDMKSAvRtEntryPoints.AvSetMmThreadPriority(hAVRT, PA_AVRT_PRIORITY_NORMAL);
  4702. paWinWDMKSAvRtEntryPoints.AvRevertMmThreadCharacteristics(hAVRT);
  4703. return;
  4704. }
  4705. SetThreadPriority(hThread, THREAD_PRIORITY_NORMAL);
  4706. timeEndPeriod(1);
  4707. }
  4708. static PaError PreparePinForStart(PaWinWdmPin* pin)
  4709. {
  4710. PaError result;
  4711. result = PinSetState(pin, KSSTATE_ACQUIRE);
  4712. if (result != paNoError)
  4713. {
  4714. goto error;
  4715. }
  4716. result = PinSetState(pin, KSSTATE_PAUSE);
  4717. if (result != paNoError)
  4718. {
  4719. goto error;
  4720. }
  4721. return result;
  4722. error:
  4723. PinSetState(pin, KSSTATE_STOP);
  4724. return result;
  4725. }
  4726. static PaError PreparePinsForStart(PaProcessThreadInfo* pInfo)
  4727. {
  4728. PaError result = paNoError;
  4729. /* Submit buffers */
  4730. if (pInfo->stream->capture.pPin)
  4731. {
  4732. if ((result = PreparePinForStart(pInfo->stream->capture.pPin)) != paNoError)
  4733. {
  4734. goto error;
  4735. }
  4736. if (pInfo->stream->capture.pPin->parentFilter->devInfo.streamingType == Type_kWaveCyclic)
  4737. {
  4738. unsigned i;
  4739. for(i=0; i < pInfo->stream->capture.noOfPackets; ++i)
  4740. {
  4741. if ((result = PinRead(pInfo->stream->capture.pPin->handle, pInfo->stream->capture.packets + i)) != paNoError)
  4742. {
  4743. goto error;
  4744. }
  4745. ++pInfo->pending;
  4746. }
  4747. }
  4748. else
  4749. {
  4750. pInfo->pending = 2;
  4751. }
  4752. }
  4753. if(pInfo->stream->render.pPin)
  4754. {
  4755. if ((result = PreparePinForStart(pInfo->stream->render.pPin)) != paNoError)
  4756. {
  4757. goto error;
  4758. }
  4759. pInfo->priming += pInfo->stream->render.noOfPackets;
  4760. ++pInfo->pending;
  4761. SetEvent(pInfo->stream->render.events[0]);
  4762. if (pInfo->stream->render.pPin->parentFilter->devInfo.streamingType == Type_kWaveCyclic)
  4763. {
  4764. unsigned i;
  4765. for(i=1; i < pInfo->stream->render.noOfPackets; ++i)
  4766. {
  4767. SetEvent(pInfo->stream->render.events[i]);
  4768. ++pInfo->pending;
  4769. }
  4770. }
  4771. }
  4772. error:
  4773. PA_DEBUG(("PreparePinsForStart = %d\n", result));
  4774. return result;
  4775. }
  4776. static PaError StartPin(PaWinWdmPin* pin)
  4777. {
  4778. return PinSetState(pin, KSSTATE_RUN);
  4779. }
  4780. static PaError StartPins(PaProcessThreadInfo* pInfo)
  4781. {
  4782. PaError result = paNoError;
  4783. /* Start the pins as synced as possible */
  4784. if (pInfo->stream->capture.pPin)
  4785. {
  4786. result = StartPin(pInfo->stream->capture.pPin);
  4787. }
  4788. if(pInfo->stream->render.pPin)
  4789. {
  4790. result = StartPin(pInfo->stream->render.pPin);
  4791. }
  4792. PA_DEBUG(("StartPins = %d\n", result));
  4793. return result;
  4794. }
  4795. static PaError StopPin(PaWinWdmPin* pin)
  4796. {
  4797. PinSetState(pin, KSSTATE_PAUSE);
  4798. PinSetState(pin, KSSTATE_STOP);
  4799. return paNoError;
  4800. }
  4801. static PaError StopPins(PaProcessThreadInfo* pInfo)
  4802. {
  4803. PaError result = paNoError;
  4804. if(pInfo->stream->render.pPin)
  4805. {
  4806. StopPin(pInfo->stream->render.pPin);
  4807. }
  4808. if(pInfo->stream->capture.pPin)
  4809. {
  4810. StopPin(pInfo->stream->capture.pPin);
  4811. }
  4812. return result;
  4813. }
  4814. typedef void (*TSetInputFrameCount)(PaUtilBufferProcessor*, unsigned long);
  4815. typedef void (*TSetInputChannel)(PaUtilBufferProcessor*, unsigned int, void *, unsigned int);
  4816. static const TSetInputFrameCount fnSetInputFrameCount[2] = { PaUtil_SetInputFrameCount, PaUtil_Set2ndInputFrameCount };
  4817. static const TSetInputChannel fnSetInputChannel[2] = { PaUtil_SetInputChannel, PaUtil_Set2ndInputChannel };
  4818. static PaError PaDoProcessing(PaProcessThreadInfo* pInfo)
  4819. {
  4820. PaError result = paNoError;
  4821. int i, framesProcessed = 0, doChannelCopy = 0;
  4822. ring_buffer_size_t inputFramesAvailable = PaUtil_GetRingBufferReadAvailable(&pInfo->stream->ringBuffer);
  4823. /* Do necessary buffer processing (which will invoke user callback if necessary) */
  4824. if (pInfo->cbResult == paContinue &&
  4825. (pInfo->renderHead != pInfo->renderTail || inputFramesAvailable))
  4826. {
  4827. unsigned processFullDuplex = pInfo->stream->capture.pPin && pInfo->stream->render.pPin && (!pInfo->priming);
  4828. PA_HP_TRACE((pInfo->stream->hLog, "DoProcessing: InputFrames=%u", inputFramesAvailable));
  4829. PaUtil_BeginCpuLoadMeasurement( &pInfo->stream->cpuLoadMeasurer );
  4830. pInfo->ti.currentTime = PaUtil_GetTime();
  4831. PaUtil_BeginBufferProcessing(&pInfo->stream->bufferProcessor, &pInfo->ti, pInfo->underover);
  4832. pInfo->underover = 0; /* Reset the (under|over)flow status */
  4833. if (pInfo->renderTail != pInfo->renderHead)
  4834. {
  4835. DATAPACKET* packet = pInfo->renderPackets[pInfo->renderTail & cPacketsArrayMask].packet;
  4836. assert(packet != 0);
  4837. assert(packet->Header.Data != 0);
  4838. PaUtil_SetOutputFrameCount(&pInfo->stream->bufferProcessor, pInfo->stream->render.framesPerBuffer);
  4839. for(i=0;i<pInfo->stream->userOutputChannels;i++)
  4840. {
  4841. /* Only write the user output channels. Leave the rest blank */
  4842. PaUtil_SetOutputChannel(&pInfo->stream->bufferProcessor,
  4843. i,
  4844. ((unsigned char*)(packet->Header.Data))+(i*pInfo->stream->render.bytesPerSample),
  4845. pInfo->stream->deviceOutputChannels);
  4846. }
  4847. /* We will do a copy to the other channels after the data has been written */
  4848. doChannelCopy = ( pInfo->stream->userOutputChannels == 1 );
  4849. }
  4850. if (inputFramesAvailable && (!pInfo->stream->userOutputChannels || inputFramesAvailable >= (int)pInfo->stream->render.framesPerBuffer))
  4851. {
  4852. unsigned wrapCntr = 0;
  4853. void* data[2] = {0};
  4854. ring_buffer_size_t size[2] = {0};
  4855. /* If full-duplex, we just extract output buffer number of frames */
  4856. if (pInfo->stream->userOutputChannels)
  4857. {
  4858. inputFramesAvailable = min(inputFramesAvailable, (int)pInfo->stream->render.framesPerBuffer);
  4859. }
  4860. inputFramesAvailable = PaUtil_GetRingBufferReadRegions(&pInfo->stream->ringBuffer,
  4861. inputFramesAvailable,
  4862. &data[0],
  4863. &size[0],
  4864. &data[1],
  4865. &size[1]);
  4866. for (wrapCntr = 0; wrapCntr < 2; ++wrapCntr)
  4867. {
  4868. if (size[wrapCntr] == 0)
  4869. break;
  4870. fnSetInputFrameCount[wrapCntr](&pInfo->stream->bufferProcessor, size[wrapCntr]);
  4871. for(i=0;i<pInfo->stream->userInputChannels;i++)
  4872. {
  4873. /* Only read as many channels as the user wants */
  4874. fnSetInputChannel[wrapCntr](&pInfo->stream->bufferProcessor,
  4875. i,
  4876. ((unsigned char*)(data[wrapCntr]))+(i*pInfo->stream->capture.bytesPerSample),
  4877. pInfo->stream->deviceInputChannels);
  4878. }
  4879. }
  4880. }
  4881. else
  4882. {
  4883. /* We haven't consumed anything from the ring buffer... */
  4884. inputFramesAvailable = 0;
  4885. /* If we have full-duplex, this is at startup, so mark no-input! */
  4886. if (pInfo->stream->userOutputChannels>0 && pInfo->stream->userInputChannels>0)
  4887. {
  4888. PA_HP_TRACE((pInfo->stream->hLog, "Input startup, marking no input."));
  4889. PaUtil_SetNoInput(&pInfo->stream->bufferProcessor);
  4890. }
  4891. }
  4892. if (processFullDuplex) /* full duplex */
  4893. {
  4894. /* Only call the EndBufferProcessing function when the total input frames == total output frames */
  4895. const unsigned long totalInputFrameCount = pInfo->stream->bufferProcessor.hostInputFrameCount[0] + pInfo->stream->bufferProcessor.hostInputFrameCount[1];
  4896. const unsigned long totalOutputFrameCount = pInfo->stream->bufferProcessor.hostOutputFrameCount[0] + pInfo->stream->bufferProcessor.hostOutputFrameCount[1];
  4897. if(totalInputFrameCount == totalOutputFrameCount && totalOutputFrameCount != 0)
  4898. {
  4899. framesProcessed = PaUtil_EndBufferProcessing(&pInfo->stream->bufferProcessor, &pInfo->cbResult);
  4900. }
  4901. else
  4902. {
  4903. framesProcessed = 0;
  4904. }
  4905. }
  4906. else
  4907. {
  4908. framesProcessed = PaUtil_EndBufferProcessing(&pInfo->stream->bufferProcessor, &pInfo->cbResult);
  4909. }
  4910. PA_HP_TRACE((pInfo->stream->hLog, "Frames processed: %u %s", framesProcessed, (pInfo->priming ? "(priming)":"")));
  4911. if( doChannelCopy )
  4912. {
  4913. DATAPACKET* packet = pInfo->renderPackets[pInfo->renderTail & cPacketsArrayMask].packet;
  4914. /* Copy the first output channel to the other channels */
  4915. switch (pInfo->stream->render.bytesPerSample)
  4916. {
  4917. case 2:
  4918. DuplicateFirstChannelInt16(packet->Header.Data, pInfo->stream->deviceOutputChannels, pInfo->stream->render.framesPerBuffer);
  4919. break;
  4920. case 3:
  4921. DuplicateFirstChannelInt24(packet->Header.Data, pInfo->stream->deviceOutputChannels, pInfo->stream->render.framesPerBuffer);
  4922. break;
  4923. case 4:
  4924. DuplicateFirstChannelInt32(packet->Header.Data, pInfo->stream->deviceOutputChannels, pInfo->stream->render.framesPerBuffer);
  4925. break;
  4926. default:
  4927. assert(0); /* Unsupported format! */
  4928. break;
  4929. }
  4930. }
  4931. PaUtil_EndCpuLoadMeasurement( &pInfo->stream->cpuLoadMeasurer, framesProcessed );
  4932. if (inputFramesAvailable)
  4933. {
  4934. PaUtil_AdvanceRingBufferReadIndex(&pInfo->stream->ringBuffer, inputFramesAvailable);
  4935. }
  4936. if (pInfo->renderTail != pInfo->renderHead)
  4937. {
  4938. if (!pInfo->stream->streamStop)
  4939. {
  4940. result = pInfo->stream->render.pPin->fnSubmitHandler(pInfo, pInfo->renderTail);
  4941. if (result != paNoError)
  4942. {
  4943. PA_HP_TRACE((pInfo->stream->hLog, "Capture submit handler failed with result %d", result));
  4944. return result;
  4945. }
  4946. }
  4947. pInfo->renderTail++;
  4948. if (!pInfo->pinsStarted && pInfo->priming == 0)
  4949. {
  4950. /* We start the pins here to allow "prime time" */
  4951. if ((result = StartPins(pInfo)) == paNoError)
  4952. {
  4953. PA_HP_TRACE((pInfo->stream->hLog, "Starting pins!"));
  4954. pInfo->pinsStarted = 1;
  4955. }
  4956. }
  4957. }
  4958. }
  4959. return result;
  4960. }
  4961. static VOID CALLBACK TimerAPCWaveRTPolledMode(
  4962. LPVOID lpArgToCompletionRoutine,
  4963. DWORD dwTimerLowValue,
  4964. DWORD dwTimerHighValue)
  4965. {
  4966. HANDLE* pHandles = (HANDLE*)lpArgToCompletionRoutine;
  4967. if (pHandles[0]) SetEvent(pHandles[0]);
  4968. if (pHandles[1]) SetEvent(pHandles[1]);
  4969. }
  4970. static DWORD GetCurrentTimeInMillisecs()
  4971. {
  4972. return timeGetTime();
  4973. }
  4974. PA_THREAD_FUNC ProcessingThread(void* pParam)
  4975. {
  4976. PaError result = paNoError;
  4977. HANDLE hAVRT = NULL;
  4978. HANDLE hTimer = NULL;
  4979. HANDLE *handleArray = NULL;
  4980. HANDLE timerEventHandles[2] = {0};
  4981. unsigned noOfHandles = 0;
  4982. unsigned captureEvents = 0;
  4983. unsigned renderEvents = 0;
  4984. unsigned timerPeriod = 0;
  4985. DWORD timeStamp[2] = {0};
  4986. PaProcessThreadInfo info;
  4987. memset(&info, 0, sizeof(PaProcessThreadInfo));
  4988. info.stream = (PaWinWdmStream*)pParam;
  4989. info.stream->threadResult = paNoError;
  4990. PA_LOGE_;
  4991. info.ti.inputBufferAdcTime = 0.0;
  4992. info.ti.currentTime = 0.0;
  4993. info.ti.outputBufferDacTime = 0.0;
  4994. PA_DEBUG(("In buffer len: %.3f ms\n",(2000*info.stream->capture.framesPerBuffer) / info.stream->streamRepresentation.streamInfo.sampleRate));
  4995. PA_DEBUG(("Out buffer len: %.3f ms\n",(2000*info.stream->render.framesPerBuffer) / info.stream->streamRepresentation.streamInfo.sampleRate));
  4996. info.timeout = (DWORD)max(
  4997. (2000*info.stream->render.framesPerBuffer/info.stream->streamRepresentation.streamInfo.sampleRate + 0.5),
  4998. (2000*info.stream->capture.framesPerBuffer/info.stream->streamRepresentation.streamInfo.sampleRate + 0.5));
  4999. info.timeout = max(info.timeout*8, 100);
  5000. timerPeriod = info.timeout;
  5001. PA_DEBUG(("Timeout = %ld ms\n",info.timeout));
  5002. /* Allocate handle array */
  5003. handleArray = (HANDLE*)PaUtil_AllocateMemory((info.stream->capture.noOfPackets + info.stream->render.noOfPackets + 1) * sizeof(HANDLE));
  5004. /* Setup handle array for WFMO */
  5005. if (info.stream->capture.pPin != 0)
  5006. {
  5007. handleArray[noOfHandles++] = info.stream->capture.events[0];
  5008. if (info.stream->capture.pPin->parentFilter->devInfo.streamingType == Type_kWaveCyclic)
  5009. {
  5010. unsigned i;
  5011. for(i=1; i < info.stream->capture.noOfPackets; ++i)
  5012. {
  5013. handleArray[noOfHandles++] = info.stream->capture.events[i];
  5014. }
  5015. }
  5016. captureEvents = noOfHandles;
  5017. renderEvents = noOfHandles;
  5018. }
  5019. if (info.stream->render.pPin != 0)
  5020. {
  5021. handleArray[noOfHandles++] = info.stream->render.events[0];
  5022. if (info.stream->render.pPin->parentFilter->devInfo.streamingType == Type_kWaveCyclic)
  5023. {
  5024. unsigned i;
  5025. for(i=1; i < info.stream->render.noOfPackets; ++i)
  5026. {
  5027. handleArray[noOfHandles++] = info.stream->render.events[i];
  5028. }
  5029. }
  5030. renderEvents = noOfHandles;
  5031. }
  5032. handleArray[noOfHandles++] = info.stream->eventAbort;
  5033. assert(noOfHandles <= (info.stream->capture.noOfPackets + info.stream->render.noOfPackets + 1));
  5034. /* Prepare render and capture pins */
  5035. if ((result = PreparePinsForStart(&info)) != paNoError)
  5036. {
  5037. PA_DEBUG(("Failed to prepare device(s)!\n"));
  5038. goto error;
  5039. }
  5040. /* Init high speed logger */
  5041. if (PaUtil_InitializeHighSpeedLog(&info.stream->hLog, 1000000) != paNoError)
  5042. {
  5043. PA_DEBUG(("Failed to init high speed logger!\n"));
  5044. goto error;
  5045. }
  5046. /* Heighten priority here */
  5047. hAVRT = BumpThreadPriority();
  5048. /* If input only, we start the pins immediately */
  5049. if (info.stream->render.pPin == 0)
  5050. {
  5051. if ((result = StartPins(&info)) != paNoError)
  5052. {
  5053. PA_DEBUG(("Failed to start device(s)!\n"));
  5054. goto error;
  5055. }
  5056. info.pinsStarted = 1;
  5057. }
  5058. /* Handle WaveRT polled mode */
  5059. {
  5060. const unsigned fs = (unsigned)info.stream->streamRepresentation.streamInfo.sampleRate;
  5061. if (info.stream->capture.pPin != 0 && info.stream->capture.pPin->pinKsSubType == SubType_kPolled)
  5062. {
  5063. timerEventHandles[0] = info.stream->capture.events[0];
  5064. timerPeriod = min(timerPeriod, (1000*info.stream->capture.framesPerBuffer)/fs);
  5065. }
  5066. if (info.stream->render.pPin != 0 && info.stream->render.pPin->pinKsSubType == SubType_kPolled)
  5067. {
  5068. timerEventHandles[1] = info.stream->render.events[0];
  5069. timerPeriod = min(timerPeriod, (1000*info.stream->render.framesPerBuffer)/fs);
  5070. }
  5071. if (timerEventHandles[0] || timerEventHandles[1])
  5072. {
  5073. LARGE_INTEGER dueTime = {0};
  5074. timerPeriod=max(timerPeriod/5,1);
  5075. PA_DEBUG(("Timer event handles=0x%04X,0x%04X period=%u ms", timerEventHandles[0], timerEventHandles[1], timerPeriod));
  5076. hTimer = CreateWaitableTimer(0, FALSE, NULL);
  5077. if (hTimer == NULL)
  5078. {
  5079. result = paUnanticipatedHostError;
  5080. goto error;
  5081. }
  5082. /* invoke first timeout immediately */
  5083. if (!SetWaitableTimer(hTimer, &dueTime, timerPeriod, TimerAPCWaveRTPolledMode, timerEventHandles, FALSE))
  5084. {
  5085. result = paUnanticipatedHostError;
  5086. goto error;
  5087. }
  5088. PA_DEBUG(("Waitable timer started, period = %u ms\n", timerPeriod));
  5089. }
  5090. }
  5091. /* Mark stream as active */
  5092. info.stream->streamActive = 1;
  5093. info.stream->threadResult = paNoError;
  5094. /* Up and running... */
  5095. SetEvent(info.stream->eventStreamStart[StreamStart_kOk]);
  5096. /* Take timestamp here */
  5097. timeStamp[0] = timeStamp[1] = GetCurrentTimeInMillisecs();
  5098. while(!info.stream->streamAbort)
  5099. {
  5100. unsigned doProcessing = 1;
  5101. unsigned wait = WaitForMultipleObjects(noOfHandles, handleArray, FALSE, 0);
  5102. unsigned eventSignalled = wait - WAIT_OBJECT_0;
  5103. DWORD dwCurrentTime = 0;
  5104. if (wait == WAIT_FAILED)
  5105. {
  5106. PA_DEBUG(("Wait failed = %ld! \n",wait));
  5107. break;
  5108. }
  5109. if (wait == WAIT_TIMEOUT)
  5110. {
  5111. wait = WaitForMultipleObjectsEx(noOfHandles, handleArray, FALSE, 50, TRUE);
  5112. eventSignalled = wait - WAIT_OBJECT_0;
  5113. }
  5114. else
  5115. {
  5116. if (eventSignalled < captureEvents)
  5117. {
  5118. if (PaUtil_GetRingBufferWriteAvailable(&info.stream->ringBuffer) == 0)
  5119. {
  5120. PA_HP_TRACE((info.stream->hLog, "!!!!! Input overflow !!!!!"));
  5121. info.underover |= paInputOverflow;
  5122. }
  5123. }
  5124. else if (eventSignalled < renderEvents)
  5125. {
  5126. if (!info.priming && info.renderHead - info.renderTail > 1)
  5127. {
  5128. PA_HP_TRACE((info.stream->hLog, "!!!!! Output underflow !!!!!"));
  5129. info.underover |= paOutputUnderflow;
  5130. }
  5131. }
  5132. }
  5133. /* Get event time */
  5134. dwCurrentTime = GetCurrentTimeInMillisecs();
  5135. /* Since we can mix capture/render devices between WaveCyclic, WaveRT polled and WaveRT notification (3x3 combinations),
  5136. we can't rely on the timeout of WFMO to check for device timeouts, we need to keep tally. */
  5137. if (info.stream->capture.pPin && (dwCurrentTime - timeStamp[0]) >= info.timeout)
  5138. {
  5139. PA_DEBUG(("Timeout for capture device (%u ms)!", info.timeout, (dwCurrentTime - timeStamp[0])));
  5140. result = paTimedOut;
  5141. break;
  5142. }
  5143. if (info.stream->render.pPin && (dwCurrentTime - timeStamp[1]) >= info.timeout)
  5144. {
  5145. PA_DEBUG(("Timeout for render device (%u ms)!", info.timeout, (dwCurrentTime - timeStamp[1])));
  5146. result = paTimedOut;
  5147. break;
  5148. }
  5149. if (wait == WAIT_IO_COMPLETION)
  5150. {
  5151. /* Waitable timer has fired! */
  5152. PA_HP_TRACE((info.stream->hLog, "WAIT_IO_COMPLETION"));
  5153. continue;
  5154. }
  5155. if (wait == WAIT_TIMEOUT)
  5156. {
  5157. continue;
  5158. }
  5159. else
  5160. {
  5161. if (eventSignalled < captureEvents)
  5162. {
  5163. if (info.stream->capture.pPin->fnEventHandler(&info, eventSignalled) == paNoError)
  5164. {
  5165. timeStamp[0] = dwCurrentTime;
  5166. /* Since we use the ring buffer, we can submit the buffers directly */
  5167. if (!info.stream->streamStop)
  5168. {
  5169. result = info.stream->capture.pPin->fnSubmitHandler(&info, info.captureTail);
  5170. if (result != paNoError)
  5171. {
  5172. PA_HP_TRACE((info.stream->hLog, "Capture submit handler failed with result %d", result));
  5173. break;
  5174. }
  5175. }
  5176. ++info.captureTail;
  5177. /* If full-duplex, let _only_ render event trigger processing. We still need the stream stop
  5178. handling working, so let that be processed anyways... */
  5179. if (info.stream->userOutputChannels > 0)
  5180. {
  5181. doProcessing = 0;
  5182. }
  5183. }
  5184. }
  5185. else if (eventSignalled < renderEvents)
  5186. {
  5187. timeStamp[1] = dwCurrentTime;
  5188. eventSignalled -= captureEvents;
  5189. info.stream->render.pPin->fnEventHandler(&info, eventSignalled);
  5190. }
  5191. else
  5192. {
  5193. assert(info.stream->streamAbort);
  5194. PA_HP_TRACE((info.stream->hLog, "Stream abort!"));
  5195. continue;
  5196. }
  5197. }
  5198. /* Handle processing */
  5199. if (doProcessing)
  5200. {
  5201. result = PaDoProcessing(&info);
  5202. if (result != paNoError)
  5203. {
  5204. PA_HP_TRACE((info.stream->hLog, "PaDoProcessing failed!"));
  5205. break;
  5206. }
  5207. }
  5208. if(info.stream->streamStop && info.cbResult != paComplete)
  5209. {
  5210. PA_HP_TRACE((info.stream->hLog, "Stream stop! pending=%d",info.pending));
  5211. info.cbResult = paComplete; /* Stop, but play remaining buffers */
  5212. }
  5213. if(info.pending<=0)
  5214. {
  5215. PA_HP_TRACE((info.stream->hLog, "pending==0 finished..."));
  5216. break;
  5217. }
  5218. if((!info.stream->render.pPin)&&(info.cbResult!=paContinue))
  5219. {
  5220. PA_HP_TRACE((info.stream->hLog, "record only cbResult=%d...",info.cbResult));
  5221. break;
  5222. }
  5223. }
  5224. PA_DEBUG(("Finished processing loop\n"));
  5225. info.stream->threadResult = result;
  5226. goto bailout;
  5227. error:
  5228. PA_DEBUG(("Error starting processing thread\n"));
  5229. /* Set the "error" event together with result */
  5230. info.stream->threadResult = result;
  5231. SetEvent(info.stream->eventStreamStart[StreamStart_kFailed]);
  5232. bailout:
  5233. if (hTimer)
  5234. {
  5235. PA_DEBUG(("Waitable timer stopped\n", timerPeriod));
  5236. CancelWaitableTimer(hTimer);
  5237. CloseHandle(hTimer);
  5238. hTimer = 0;
  5239. }
  5240. if (info.pinsStarted)
  5241. {
  5242. StopPins(&info);
  5243. }
  5244. /* Lower prio here */
  5245. DropThreadPriority(hAVRT);
  5246. if (handleArray != NULL)
  5247. {
  5248. PaUtil_FreeMemory(handleArray);
  5249. }
  5250. #if PA_TRACE_REALTIME_EVENTS
  5251. if (info.stream->hLog)
  5252. {
  5253. PA_DEBUG(("Dumping highspeed trace...\n"));
  5254. PaUtil_DumpHighSpeedLog(info.stream->hLog, "hp_trace.log");
  5255. PaUtil_DiscardHighSpeedLog(info.stream->hLog);
  5256. info.stream->hLog = 0;
  5257. }
  5258. #endif
  5259. info.stream->streamActive = 0;
  5260. if((!info.stream->streamStop)&&(!info.stream->streamAbort))
  5261. {
  5262. /* Invoke the user stream finished callback */
  5263. /* Only do it from here if not being stopped/aborted by user */
  5264. if( info.stream->streamRepresentation.streamFinishedCallback != 0 )
  5265. info.stream->streamRepresentation.streamFinishedCallback( info.stream->streamRepresentation.userData );
  5266. }
  5267. info.stream->streamStop = 0;
  5268. info.stream->streamAbort = 0;
  5269. PA_LOGL_;
  5270. return 0;
  5271. }
  5272. static PaError StartStream( PaStream *s )
  5273. {
  5274. PaError result = paNoError;
  5275. PaWinWdmStream *stream = (PaWinWdmStream*)s;
  5276. PA_LOGE_;
  5277. if (stream->streamThread != NULL)
  5278. {
  5279. return paStreamIsNotStopped;
  5280. }
  5281. stream->streamStop = 0;
  5282. stream->streamAbort = 0;
  5283. ResetStreamEvents(stream);
  5284. PaUtil_ResetBufferProcessor( &stream->bufferProcessor );
  5285. stream->oldProcessPriority = GetPriorityClass(GetCurrentProcess());
  5286. /* Uncomment the following line to enable dynamic boosting of the process
  5287. * priority to real time for best low latency support
  5288. * Disabled by default because RT processes can easily block the OS */
  5289. /*ret = SetPriorityClass(GetCurrentProcess(),REALTIME_PRIORITY_CLASS);
  5290. PA_DEBUG(("Class ret = %d;",ret));*/
  5291. stream->streamThread = CREATE_THREAD_FUNCTION (NULL, 0, ProcessingThread, stream, CREATE_SUSPENDED, NULL);
  5292. if(stream->streamThread == NULL)
  5293. {
  5294. result = paInsufficientMemory;
  5295. goto end;
  5296. }
  5297. ResumeThread(stream->streamThread);
  5298. switch (WaitForMultipleObjects(2, stream->eventStreamStart, FALSE, 5000))
  5299. {
  5300. case WAIT_OBJECT_0 + StreamStart_kOk:
  5301. PA_DEBUG(("Processing thread started!\n"));
  5302. result = paNoError;
  5303. /* streamActive is set in processing thread */
  5304. stream->streamStarted = 1;
  5305. break;
  5306. case WAIT_OBJECT_0 + StreamStart_kFailed:
  5307. PA_DEBUG(("Processing thread start failed! (result=%d)\n", stream->threadResult));
  5308. result = stream->threadResult;
  5309. /* Wait for the stream to really exit */
  5310. WaitForSingleObject(stream->streamThread, 200);
  5311. CloseHandle(stream->streamThread);
  5312. stream->streamThread = 0;
  5313. break;
  5314. case WAIT_TIMEOUT:
  5315. default:
  5316. result = paTimedOut;
  5317. PaWinWDM_SetLastErrorInfo(result, "Failed to start processing thread (timeout)!");
  5318. break;
  5319. }
  5320. end:
  5321. PA_LOGL_;
  5322. return result;
  5323. }
  5324. static PaError StopStream( PaStream *s )
  5325. {
  5326. PaError result = paNoError;
  5327. PaWinWdmStream *stream = (PaWinWdmStream*)s;
  5328. BOOL doCb = FALSE;
  5329. PA_LOGE_;
  5330. if(stream->streamActive)
  5331. {
  5332. DWORD dwExitCode;
  5333. doCb = TRUE;
  5334. stream->streamStop = 1;
  5335. if (GetExitCodeThread(stream->streamThread, &dwExitCode) && dwExitCode == STILL_ACTIVE)
  5336. {
  5337. if (WaitForSingleObject(stream->streamThread, INFINITE) != WAIT_OBJECT_0)
  5338. {
  5339. PA_DEBUG(("StopStream: stream thread terminated\n"));
  5340. TerminateThread(stream->streamThread, -1);
  5341. result = paTimedOut;
  5342. }
  5343. }
  5344. else
  5345. {
  5346. PA_DEBUG(("StopStream: GECT says not active, but streamActive is not false ??"));
  5347. result = paUnanticipatedHostError;
  5348. PaWinWDM_SetLastErrorInfo(result, "StopStream: GECT says not active, but streamActive = %d", stream->streamActive);
  5349. }
  5350. }
  5351. else
  5352. {
  5353. if (stream->threadResult != paNoError)
  5354. {
  5355. PA_DEBUG(("StopStream: Stream not active (%d)\n", stream->threadResult));
  5356. result = stream->threadResult;
  5357. stream->threadResult = paNoError;
  5358. }
  5359. }
  5360. if (stream->streamThread != NULL)
  5361. {
  5362. CloseHandle(stream->streamThread);
  5363. stream->streamThread = 0;
  5364. }
  5365. stream->streamStarted = 0;
  5366. stream->streamActive = 0;
  5367. if(doCb)
  5368. {
  5369. /* Do user callback now after all state has been reset */
  5370. /* This means it should be safe for the called function */
  5371. /* to invoke e.g. StartStream */
  5372. if( stream->streamRepresentation.streamFinishedCallback != 0 )
  5373. stream->streamRepresentation.streamFinishedCallback( stream->streamRepresentation.userData );
  5374. }
  5375. PA_LOGL_;
  5376. return result;
  5377. }
  5378. static PaError AbortStream( PaStream *s )
  5379. {
  5380. PaError result = paNoError;
  5381. PaWinWdmStream *stream = (PaWinWdmStream*)s;
  5382. int doCb = 0;
  5383. PA_LOGE_;
  5384. if(stream->streamActive)
  5385. {
  5386. doCb = 1;
  5387. stream->streamAbort = 1;
  5388. SetEvent(stream->eventAbort); /* Signal immediately */
  5389. if (WaitForSingleObject(stream->streamThread, 10000) != WAIT_OBJECT_0)
  5390. {
  5391. TerminateThread(stream->streamThread, -1);
  5392. result = paTimedOut;
  5393. PA_DEBUG(("AbortStream: stream thread terminated\n"));
  5394. }
  5395. assert(!stream->streamActive);
  5396. }
  5397. CloseHandle(stream->streamThread);
  5398. stream->streamThread = NULL;
  5399. stream->streamStarted = 0;
  5400. if(doCb)
  5401. {
  5402. /* Do user callback now after all state has been reset */
  5403. /* This means it should be safe for the called function */
  5404. /* to invoke e.g. StartStream */
  5405. if( stream->streamRepresentation.streamFinishedCallback != 0 )
  5406. stream->streamRepresentation.streamFinishedCallback( stream->streamRepresentation.userData );
  5407. }
  5408. stream->streamActive = 0;
  5409. stream->streamStarted = 0;
  5410. PA_LOGL_;
  5411. return result;
  5412. }
  5413. static PaError IsStreamStopped( PaStream *s )
  5414. {
  5415. PaWinWdmStream *stream = (PaWinWdmStream*)s;
  5416. int result = 0;
  5417. PA_LOGE_;
  5418. if(!stream->streamStarted)
  5419. result = 1;
  5420. PA_LOGL_;
  5421. return result;
  5422. }
  5423. static PaError IsStreamActive( PaStream *s )
  5424. {
  5425. PaWinWdmStream *stream = (PaWinWdmStream*)s;
  5426. int result = 0;
  5427. PA_LOGE_;
  5428. if(stream->streamActive)
  5429. result = 1;
  5430. PA_LOGL_;
  5431. return result;
  5432. }
  5433. static PaTime GetStreamTime( PaStream* s )
  5434. {
  5435. PA_LOGE_;
  5436. PA_LOGL_;
  5437. (void)s;
  5438. return PaUtil_GetTime();
  5439. }
  5440. static double GetStreamCpuLoad( PaStream* s )
  5441. {
  5442. PaWinWdmStream *stream = (PaWinWdmStream*)s;
  5443. double result;
  5444. PA_LOGE_;
  5445. result = PaUtil_GetCpuLoad( &stream->cpuLoadMeasurer );
  5446. PA_LOGL_;
  5447. return result;
  5448. }
  5449. /*
  5450. As separate stream interfaces are used for blocking and callback
  5451. streams, the following functions can be guaranteed to only be called
  5452. for blocking streams.
  5453. */
  5454. static PaError ReadStream( PaStream* s,
  5455. void *buffer,
  5456. unsigned long frames )
  5457. {
  5458. PaWinWdmStream *stream = (PaWinWdmStream*)s;
  5459. PA_LOGE_;
  5460. /* suppress unused variable warnings */
  5461. (void) buffer;
  5462. (void) frames;
  5463. (void) stream;
  5464. /* IMPLEMENT ME, see portaudio.h for required behavior*/
  5465. PA_LOGL_;
  5466. return paInternalError;
  5467. }
  5468. static PaError WriteStream( PaStream* s,
  5469. const void *buffer,
  5470. unsigned long frames )
  5471. {
  5472. PaWinWdmStream *stream = (PaWinWdmStream*)s;
  5473. PA_LOGE_;
  5474. /* suppress unused variable warnings */
  5475. (void) buffer;
  5476. (void) frames;
  5477. (void) stream;
  5478. /* IMPLEMENT ME, see portaudio.h for required behavior*/
  5479. PA_LOGL_;
  5480. return paInternalError;
  5481. }
  5482. static signed long GetStreamReadAvailable( PaStream* s )
  5483. {
  5484. PaWinWdmStream *stream = (PaWinWdmStream*)s;
  5485. PA_LOGE_;
  5486. /* suppress unused variable warnings */
  5487. (void) stream;
  5488. /* IMPLEMENT ME, see portaudio.h for required behavior*/
  5489. PA_LOGL_;
  5490. return 0;
  5491. }
  5492. static signed long GetStreamWriteAvailable( PaStream* s )
  5493. {
  5494. PaWinWdmStream *stream = (PaWinWdmStream*)s;
  5495. PA_LOGE_;
  5496. /* suppress unused variable warnings */
  5497. (void) stream;
  5498. /* IMPLEMENT ME, see portaudio.h for required behavior*/
  5499. PA_LOGL_;
  5500. return 0;
  5501. }
  5502. /***************************************************************************************/
  5503. /* Event and submit handlers for WaveCyclic */
  5504. /***************************************************************************************/
  5505. static PaError PaPinCaptureEventHandler_WaveCyclic(PaProcessThreadInfo* pInfo, unsigned eventIndex)
  5506. {
  5507. PaError result = paNoError;
  5508. ring_buffer_size_t frameCount;
  5509. DATAPACKET* packet = pInfo->stream->capture.packets + eventIndex;
  5510. assert( eventIndex < pInfo->stream->capture.noOfPackets );
  5511. if (packet->Header.DataUsed == 0)
  5512. {
  5513. PA_HP_TRACE((pInfo->stream->hLog, ">>> Capture bogus event (no data): idx=%u", eventIndex));
  5514. /* Bogus event, reset! This is to handle the behavior of this USB mic: http://shop.xtz.se/measurement-system/microphone-to-dirac-live-room-correction-suite
  5515. on startup of streaming, where it erroneously sets the event without the corresponding buffer being filled (DataUsed == 0) */
  5516. ResetEvent(packet->Signal.hEvent);
  5517. result = -1; /* Only need this to be NOT paNoError */
  5518. }
  5519. else
  5520. {
  5521. pInfo->capturePackets[pInfo->captureHead & cPacketsArrayMask].packet = packet;
  5522. frameCount = PaUtil_WriteRingBuffer(&pInfo->stream->ringBuffer, packet->Header.Data, pInfo->stream->capture.framesPerBuffer);
  5523. PA_HP_TRACE((pInfo->stream->hLog, ">>> Capture event: idx=%u (frames=%u)", eventIndex, frameCount));
  5524. ++pInfo->captureHead;
  5525. }
  5526. --pInfo->pending; /* This needs to be done in either case */
  5527. return result;
  5528. }
  5529. static PaError PaPinCaptureSubmitHandler_WaveCyclic(PaProcessThreadInfo* pInfo, unsigned eventIndex)
  5530. {
  5531. PaError result = paNoError;
  5532. DATAPACKET* packet = pInfo->capturePackets[pInfo->captureTail & cPacketsArrayMask].packet;
  5533. pInfo->capturePackets[pInfo->captureTail & cPacketsArrayMask].packet = 0;
  5534. assert(packet != 0);
  5535. PA_HP_TRACE((pInfo->stream->hLog, "Capture submit: %u", eventIndex));
  5536. packet->Header.DataUsed = 0; /* Reset for reuse */
  5537. ResetEvent(packet->Signal.hEvent);
  5538. result = PinRead(pInfo->stream->capture.pPin->handle, packet);
  5539. ++pInfo->pending;
  5540. return result;
  5541. }
  5542. static PaError PaPinRenderEventHandler_WaveCyclic(PaProcessThreadInfo* pInfo, unsigned eventIndex)
  5543. {
  5544. assert( eventIndex < pInfo->stream->render.noOfPackets );
  5545. pInfo->renderPackets[pInfo->renderHead & cPacketsArrayMask].packet = pInfo->stream->render.packets + eventIndex;
  5546. PA_HP_TRACE((pInfo->stream->hLog, "<<< Render event : idx=%u head=%u", eventIndex, pInfo->renderHead));
  5547. ++pInfo->renderHead;
  5548. --pInfo->pending;
  5549. return paNoError;
  5550. }
  5551. static PaError PaPinRenderSubmitHandler_WaveCyclic(PaProcessThreadInfo* pInfo, unsigned eventIndex)
  5552. {
  5553. PaError result = paNoError;
  5554. DATAPACKET* packet = pInfo->renderPackets[pInfo->renderTail & cPacketsArrayMask].packet;
  5555. pInfo->renderPackets[pInfo->renderTail & cPacketsArrayMask].packet = 0;
  5556. assert(packet != 0);
  5557. PA_HP_TRACE((pInfo->stream->hLog, "Render submit : %u idx=%u", pInfo->renderTail, (unsigned)(packet - pInfo->stream->render.packets)));
  5558. ResetEvent(packet->Signal.hEvent);
  5559. result = PinWrite(pInfo->stream->render.pPin->handle, packet);
  5560. /* Reset event, just in case we have an analogous situation to capture (see PaPinCaptureSubmitHandler_WaveCyclic) */
  5561. ++pInfo->pending;
  5562. if (pInfo->priming)
  5563. {
  5564. --pInfo->priming;
  5565. }
  5566. return result;
  5567. }
  5568. /***************************************************************************************/
  5569. /* Event and submit handlers for WaveRT */
  5570. /***************************************************************************************/
  5571. static PaError PaPinCaptureEventHandler_WaveRTEvent(PaProcessThreadInfo* pInfo, unsigned eventIndex)
  5572. {
  5573. unsigned long pos;
  5574. unsigned realInBuf;
  5575. unsigned frameCount;
  5576. PaWinWdmIOInfo* pCapture = &pInfo->stream->capture;
  5577. const unsigned halfInputBuffer = pCapture->hostBufferSize >> 1;
  5578. PaWinWdmPin* pin = pCapture->pPin;
  5579. DATAPACKET* packet = 0;
  5580. /* Get hold of current ADC position */
  5581. pin->fnAudioPosition(pin, &pos);
  5582. /* Wrap it (robi: why not use hw latency compensation here ?? because pos then gets _way_ off from
  5583. where it should be, i.e. at beginning or half buffer position. Why? No idea.) */
  5584. pos %= pCapture->hostBufferSize;
  5585. /* Then realInBuf will point to "other" half of double buffer */
  5586. realInBuf = pos < halfInputBuffer ? 1U : 0U;
  5587. packet = pInfo->stream->capture.packets + realInBuf;
  5588. /* Call barrier (or dummy) */
  5589. pin->fnMemBarrier();
  5590. /* Put it in queue */
  5591. frameCount = PaUtil_WriteRingBuffer(&pInfo->stream->ringBuffer, packet->Header.Data, pCapture->framesPerBuffer);
  5592. pInfo->capturePackets[pInfo->captureHead & cPacketsArrayMask].packet = packet;
  5593. PA_HP_TRACE((pInfo->stream->hLog, "Capture event (WaveRT): idx=%u head=%u (pos = %4.1lf%%, frames=%u)", realInBuf, pInfo->captureHead, (pos * 100.0 / pCapture->hostBufferSize), frameCount));
  5594. ++pInfo->captureHead;
  5595. --pInfo->pending;
  5596. return paNoError;
  5597. }
  5598. static PaError PaPinCaptureEventHandler_WaveRTPolled(PaProcessThreadInfo* pInfo, unsigned eventIndex)
  5599. {
  5600. unsigned long pos;
  5601. unsigned bytesToRead;
  5602. PaWinWdmIOInfo* pCapture = &pInfo->stream->capture;
  5603. const unsigned halfInputBuffer = pCapture->hostBufferSize>>1;
  5604. PaWinWdmPin* pin = pInfo->stream->capture.pPin;
  5605. /* Get hold of current ADC position */
  5606. pin->fnAudioPosition(pin, &pos);
  5607. /* Wrap it (robi: why not use hw latency compensation here ?? because pos then gets _way_ off from
  5608. where it should be, i.e. at beginning or half buffer position. Why? No idea.) */
  5609. /* Compensate for HW FIFO to get to last read buffer position */
  5610. pos += pin->hwLatency;
  5611. pos %= pCapture->hostBufferSize;
  5612. /* Need to align position on frame boundary */
  5613. pos &= ~(pCapture->bytesPerFrame - 1);
  5614. /* Call barrier (or dummy) */
  5615. pin->fnMemBarrier();
  5616. /* Put it in "queue" */
  5617. bytesToRead = (pCapture->hostBufferSize + pos - pCapture->lastPosition) % pCapture->hostBufferSize;
  5618. if (bytesToRead > 0)
  5619. {
  5620. unsigned frameCount = PaUtil_WriteRingBuffer(&pInfo->stream->ringBuffer,
  5621. pCapture->hostBuffer + pCapture->lastPosition,
  5622. bytesToRead / pCapture->bytesPerFrame);
  5623. pCapture->lastPosition = (pCapture->lastPosition + frameCount * pCapture->bytesPerFrame) % pCapture->hostBufferSize;
  5624. PA_HP_TRACE((pInfo->stream->hLog, "Capture event (WaveRTPolled): pos = %4.1lf%%, framesRead=%u", (pos * 100.0 / pCapture->hostBufferSize), frameCount));
  5625. ++pInfo->captureHead;
  5626. --pInfo->pending;
  5627. }
  5628. return paNoError;
  5629. }
  5630. static PaError PaPinCaptureSubmitHandler_WaveRTEvent(PaProcessThreadInfo* pInfo, unsigned eventIndex)
  5631. {
  5632. pInfo->capturePackets[pInfo->captureTail & cPacketsArrayMask].packet = 0;
  5633. ++pInfo->pending;
  5634. return paNoError;
  5635. }
  5636. static PaError PaPinCaptureSubmitHandler_WaveRTPolled(PaProcessThreadInfo* pInfo, unsigned eventIndex)
  5637. {
  5638. pInfo->capturePackets[pInfo->captureTail & cPacketsArrayMask].packet = 0;
  5639. ++pInfo->pending;
  5640. return paNoError;
  5641. }
  5642. static PaError PaPinRenderEventHandler_WaveRTEvent(PaProcessThreadInfo* pInfo, unsigned eventIndex)
  5643. {
  5644. unsigned long pos;
  5645. unsigned realOutBuf;
  5646. PaWinWdmIOInfo* pRender = &pInfo->stream->render;
  5647. const unsigned halfOutputBuffer = pRender->hostBufferSize >> 1;
  5648. PaWinWdmPin* pin = pInfo->stream->render.pPin;
  5649. PaIOPacket* ioPacket = &pInfo->renderPackets[pInfo->renderHead & cPacketsArrayMask];
  5650. /* Get hold of current DAC position */
  5651. pin->fnAudioPosition(pin, &pos);
  5652. /* Compensate for HW FIFO to get to last read buffer position */
  5653. pos += pin->hwLatency;
  5654. /* Wrap it */
  5655. pos %= pRender->hostBufferSize;
  5656. /* And align it, not sure its really needed though */
  5657. pos &= ~(pRender->bytesPerFrame - 1);
  5658. /* Then realOutBuf will point to "other" half of double buffer */
  5659. realOutBuf = pos < halfOutputBuffer ? 1U : 0U;
  5660. if (pInfo->priming)
  5661. {
  5662. realOutBuf = pInfo->renderHead & 0x1;
  5663. }
  5664. ioPacket->packet = pInfo->stream->render.packets + realOutBuf;
  5665. ioPacket->startByte = realOutBuf * halfOutputBuffer;
  5666. ioPacket->lengthBytes = halfOutputBuffer;
  5667. PA_HP_TRACE((pInfo->stream->hLog, "Render event (WaveRT) : idx=%u head=%u (pos = %4.1lf%%)", realOutBuf, pInfo->renderHead, (pos * 100.0 / pRender->hostBufferSize) ));
  5668. ++pInfo->renderHead;
  5669. --pInfo->pending;
  5670. return paNoError;
  5671. }
  5672. static PaError PaPinRenderEventHandler_WaveRTPolled(PaProcessThreadInfo* pInfo, unsigned eventIndex)
  5673. {
  5674. unsigned long pos;
  5675. unsigned realOutBuf;
  5676. unsigned bytesToWrite;
  5677. PaWinWdmIOInfo* pRender = &pInfo->stream->render;
  5678. const unsigned halfOutputBuffer = pRender->hostBufferSize >> 1;
  5679. PaWinWdmPin* pin = pInfo->stream->render.pPin;
  5680. PaIOPacket* ioPacket = &pInfo->renderPackets[pInfo->renderHead & cPacketsArrayMask];
  5681. /* Get hold of current DAC position */
  5682. pin->fnAudioPosition(pin, &pos);
  5683. /* Compensate for HW FIFO to get to last read buffer position */
  5684. pos += pin->hwLatency;
  5685. /* Wrap it */
  5686. pos %= pRender->hostBufferSize;
  5687. /* And align it, not sure its really needed though */
  5688. pos &= ~(pRender->bytesPerFrame - 1);
  5689. if (pInfo->priming)
  5690. {
  5691. realOutBuf = pInfo->renderHead & 0x1;
  5692. ioPacket->packet = pInfo->stream->render.packets + realOutBuf;
  5693. ioPacket->startByte = realOutBuf * halfOutputBuffer;
  5694. ioPacket->lengthBytes = halfOutputBuffer;
  5695. ++pInfo->renderHead;
  5696. --pInfo->pending;
  5697. }
  5698. else
  5699. {
  5700. bytesToWrite = (pRender->hostBufferSize + pos - pRender->lastPosition) % pRender->hostBufferSize;
  5701. ++pRender->pollCntr;
  5702. if (bytesToWrite >= halfOutputBuffer)
  5703. {
  5704. realOutBuf = (pos < halfOutputBuffer) ? 1U : 0U;
  5705. ioPacket->packet = pInfo->stream->render.packets + realOutBuf;
  5706. pRender->lastPosition = realOutBuf ? 0U : halfOutputBuffer;
  5707. ioPacket->startByte = realOutBuf * halfOutputBuffer;
  5708. ioPacket->lengthBytes = halfOutputBuffer;
  5709. ++pInfo->renderHead;
  5710. --pInfo->pending;
  5711. PA_HP_TRACE((pInfo->stream->hLog, "Render event (WaveRTPolled) : idx=%u head=%u (pos = %4.1lf%%, cnt=%u)", realOutBuf, pInfo->renderHead, (pos * 100.0 / pRender->hostBufferSize), pRender->pollCntr));
  5712. pRender->pollCntr = 0;
  5713. }
  5714. }
  5715. return paNoError;
  5716. }
  5717. static PaError PaPinRenderSubmitHandler_WaveRTEvent(PaProcessThreadInfo* pInfo, unsigned eventIndex)
  5718. {
  5719. PaWinWdmPin* pin = pInfo->stream->render.pPin;
  5720. pInfo->renderPackets[pInfo->renderTail & cPacketsArrayMask].packet = 0;
  5721. /* Call barrier (if needed) */
  5722. pin->fnMemBarrier();
  5723. PA_HP_TRACE((pInfo->stream->hLog, "Render submit (WaveRT) : submit=%u", pInfo->renderTail));
  5724. ++pInfo->pending;
  5725. if (pInfo->priming)
  5726. {
  5727. --pInfo->priming;
  5728. if (pInfo->priming)
  5729. {
  5730. PA_HP_TRACE((pInfo->stream->hLog, "Setting WaveRT event for priming (2)"));
  5731. SetEvent(pInfo->stream->render.events[0]);
  5732. }
  5733. }
  5734. return paNoError;
  5735. }
  5736. static PaError PaPinRenderSubmitHandler_WaveRTPolled(PaProcessThreadInfo* pInfo, unsigned eventIndex)
  5737. {
  5738. PaWinWdmPin* pin = pInfo->stream->render.pPin;
  5739. pInfo->renderPackets[pInfo->renderTail & cPacketsArrayMask].packet = 0;
  5740. /* Call barrier (if needed) */
  5741. pin->fnMemBarrier();
  5742. PA_HP_TRACE((pInfo->stream->hLog, "Render submit (WaveRTPolled) : submit=%u", pInfo->renderTail));
  5743. ++pInfo->pending;
  5744. if (pInfo->priming)
  5745. {
  5746. --pInfo->priming;
  5747. if (pInfo->priming)
  5748. {
  5749. PA_HP_TRACE((pInfo->stream->hLog, "Setting WaveRT event for priming (2)"));
  5750. SetEvent(pInfo->stream->render.events[0]);
  5751. }
  5752. }
  5753. return paNoError;
  5754. }